RXJS - 嵌套 concapMap 是否等同于顺序 concatMap?

Flo*_*ian 2 javascript rxjs concatmap

当使用 RXJS 时,我问自己嵌套的 concatMap 是否等同于顺序的。考虑以下示例:

observable1.pipe(
   concatMap(result1 => observable2.pipe(
      concatMap(result2 => observable3.pipe(
         concatMap(result3 => of(result3)
      )
   )
).susbcribe((result) => {...});
Run Code Online (Sandbox Code Playgroud)

这将result导致result3. 为了避免嵌套,我想写成如下:

of(null).pipe(
   concatMap(() => observable1),
   concatMap(result1 => observable2),
   concatMap(result2 => observable3),
   concatMap(result3 => of(result3))
).susbcribe((result) => {...});
Run Code Online (Sandbox Code Playgroud)

这也会导致result存在result3。即使在细节级别上可能存在差异,我是否可以假设连接可观察量的两种方法都被认为是等效的(例如,关于失败)?

任何帮助表示赞赏...

fri*_*doo 5

不,它们在所有情况下的行为方式并不相同。

\n

嵌套ConcatMap

\n
observable1.pipe(\n  concatMap(result1 => inner2)\n)\n\ninner2 = observable2.pipe(\n  concatMap(result2 => observable3.pipe(\n    concatMap(result3 => of(result3))\n  ))\n))\n
Run Code Online (Sandbox Code Playgroud)\n

observable1将从上一个可观察值完成inner2时映射下一个值inner2

\n

顺序连接映射

\n
observable1.pipe(\n  concatMap(result1 => observable2),\n  concatMap(result2 => observable3),\n  concatMap(result3 => of(result3))\n)\n
Run Code Online (Sandbox Code Playgroud)\n

将映射下一个值到observable1observable2一个值完成时observable2

\n

您在最终订阅回调中收到的结果将是相同的,并且将以相同的顺序到达。但是您收到这些结果的时间可能会有所不同,因为Nested ConcatMap中的可观察量可能会inner2晚于Sequential ConcatMap中的可观察量映射到后续可observable2观察量,因为inner2可能需要比 更长的时间才能完成observable2

\n

例子

\n

obs_1使用三个可观察量和obs_2来说明事件发生顺序的示例obs_3https://stackblitz.com/edit/rxjs-mxfdtn? file=index.ts 。

\n

对于 Nested ConcatMap ,obs_2obs_3是同一内部可观察量 ( inner2) 的一部分,因此仅在第 1 个(包含 1st 、 1st 、 2nd )完成inner2后才订阅第 2 个。对于 Sequential ConcatMap,第一个完成后就会订阅第二个。inner2obs_2obs_3obs_3obs_2obs_2

\n
obs_1: --11--12|\nobs_2: --21--22|\nobs_3: --31--32|\n\n// Nested ConcatMap\n   \xe2\x9d\xb6\n--11--12|~~~~~~~~~~~~~~~~~12\n   \xe2\x94\x82                       \xe2\x94\x94--21--22|~~~22\n   \xe2\x94\x82                           \xe2\x94\x82         \xe2\x94\x94--31--32|\n   \xe2\x94\x82        \xe2\x9d\xb7             \xe2\x9d\xb8    \xe2\x94\x94--31--32|\n   \xe2\x94\x94--21--22|~~~22        |\n       \xe2\x94\x82         \xe2\x94\x94--31--32|    \n       \xe2\x94\x94--31--32|              \n\noutput: --31--32----31--32--------31--32----31--32|\n\n\n// Sequential ConcatMap\n   \xe2\x9d\xb6\n--11--12|~~~12\n   \xe2\x94\x82         \xe2\x94\x94--21--22|~~~21~~~~~~~~22\n   \xe2\x94\x82                       \xe2\x94\x82         \xe2\x94\x94--31--32|\n   \xe2\x94\x82        \xe2\x9d\xb7              \xe2\x94\x94--31--32|\n   \xe2\x94\x94--21--22|~~~22        \xe2\x9d\xb8\n       \xe2\x94\x82         \xe2\x94\x94--31--32|\n       \xe2\x94\x94--31--32|\n\noutput: --31--32----31--32----31--32----31--32|\n\n\nx~~~x    x is emitted at the first position but concatMap is holding the value \n    \xe2\x94\x94O   back and waits with ~ until a previous observable completes and then \n         maps the value to the observable O.\n
Run Code Online (Sandbox Code Playgroud)\n
\xe2\x9d\xb6        start of the 1st obs_2. For Nested ConcatMap this also marks the start of \n         the 1st inner2.\n\n\xe2\x9d\xb7        The 1st obs_2 completed but the 1st inner2 hasn\'t completed yet.\n         Nested ConcatMap waits until the 1st inner2 completes before it maps 12 to \n         the 2nd inner2. Sequential ConcatMap will map 12 to the 2nd obs_2 straight away. \n\n\xe2\x9d\xb8        The 1st inner2 completed. Nested ConcatMap maps 12 to the 2nd inner2.\n         Sequential ConcatMap has already mapped 12 to the 2nd obs_2 by this time\n         and this 2nd obs_2 has already emitted both values and completed but concatMap\n         has buffered those values until now.\n
Run Code Online (Sandbox Code Playgroud)\n

正如您所看到的,顺序 ConcatMap 方法obs_2比嵌套 ConcatMap 方法更早地订阅第二个可观察值。

\n