在RxJS中,switchMap、concatMap、mergeMap和exhaustMap都是高阶映射操作符(Higher-Order Mapping Operators),用于将一个Observable的值映射成另一个Observable(内部Observable),然后订阅它。它们的差异在于如何处理内部Observable的订阅和取消订阅,尤其是在源Observable发出新值而内部Observable尚未完成时。
switchMap
- 行为:当源 Observable 发出新值时,立即取消上一个未完成的内部 Observable,并切换到新的内部 Observable。
- 适用场景:只关心最新请求的结果(如用户连续输入搜索词时,自动取消未完成的旧请求,只保留最新请求的结果)。
concatMap
- 行为:严格按顺序执行内部 Observable。前一个内部 Observable 未完成时,新值会被缓存,直到前一个完成后再按顺序执行。
- 适用场景:需要严格保证顺序的任务(如文件上传队列、数据库顺序写入)
mergeMap
- 行为:同时启动所有内部 Observable,允许并发执行(可通过参数
concurrent限制并发数)。不保证完成顺序。 - 适用场景:允许并发的独立任务(如批量下载文件)。
exhaustMap
- 行为:当内部 Observable 未完成时,忽略所有新值。只有当前内部 Observable 完成后,才接受下一个新值。
- 适用场景:如按钮防止重复提交
总结
- 需要最新结果 →
switchMap - 需严格顺序执行 →
concatMap - 允许并发且顺序无关 →
mergeMap - 需忽略重复请求 →
exhaustMap
理解这些差异能有效避免竞态条件和资源浪费,根据场景选择正确的操作符是 RxJS 高效应用的关键。选择正确的操作符,本质是根据业务场景制定异步操作的冲突解决策略,从而保证数据一致性和用户体验。