You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何传入恒等函数时RxJS的mergeMap会执行扁平化操作?

RxJS mergeMap 行为差异解析

核心逻辑:mergeMap 的 Observable 转换规则

mergeMap 的核心是将投影函数的返回值转换为 Observable,再把这个 Observable 发射的内容扁平化到下游流中。不同类型的返回值,RxJS 会采用不同的转换逻辑:

1. 返回数组时:自动拆分为单个元素

RxJS 会把数组识别为「类 Observable 对象」,内部等同于调用 from(数组) —— 这会将数组的每个元素依次发射出去。

对应你的第一段代码:

of(['click', 'tap'])
  .pipe(
      mergeMap(_ => _), // 投影函数直接返回数组['click', 'tap']
      tap(console.log) // 依次接收'click'、'tap',触发两次
  )
  .subscribe();

这里 mergeMap(_ => _) 和 mergeMap(val => from(val)) 效果完全一致,数组被拆分为单个元素,所以下游会收到两次值。

2. 返回 Promise 时:仅发射完整的 Promise 结果

Promise 的特性是一次性返回完整结果,哪怕你用 Promise.resolve(数组),它也会把整个数组当作单一值返回。RxJS 将 Promise 转换为 Observable 后,这个 Observable 只会发射一次,值就是 Promise resolve 的完整数组。

对应你的第二段代码:

of(['click', 'tap'])
  .pipe(
      mergeMap(_ => Promise.resolve(_)), // 返回的Promise将整个数组作为单一结果resolve
      tap(console.log) // 仅接收一次完整数组['click', 'tap']
  )
  .subscribe();

因此下游只会触发一次 tap 回调。

扩展:让 Promise 场景也实现扁平化

如果希望在返回 Promise 的场景下也拆分数组元素,需要手动将 Promise 返回的数组转换为 Observable:

of(['click', 'tap'])
  .pipe(
      mergeMap(_ => Promise.resolve(_).then(arr => from(arr))),
      tap(console.log) // 同样依次接收'click'、'tap'
  )
  .subscribe();

内容的提问来源于stack exchange,提问作者Thodoris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 05:50:21