2

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

observable1.pipe(
   concatMap(result1 => observable2.pipe(
      concatMap(result2 => observable3.pipe(
         concatMap(result3 => of(result3)
      )
   )
).susbcribe((result) => {...});

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

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

这也将导致result存在result3。即使在细节层面上可能存在差异,我是否可以假设连接 observable 的两种方法都被认为是等效的(例如,对于失败)?

任何帮助表示赞赏...

4

1 回答 1

4

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

嵌套的 ConcatMap

observable1.pipe(
  concatMap(result1 => inner2)
)

inner2 = observable2.pipe(
  concatMap(result2 => observable3.pipe(
    concatMap(result3 => of(result3))
  ))
))

将下一个值映射observable1inner2前一个inner2可观察对象完成的时间。

顺序 ConcatMap

observable1.pipe(
  concatMap(result1 => observable2),
  concatMap(result2 => observable3),
  concatMap(result3 => of(result3))
)

将下一个值映射observable1observable2上一个observable2完成的时间。

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

例子

obs_1使用三个 observable和:httpsobs_2 ://stackblitz.com/edit/rxjs-mxfdtn? file = index.ts 的事件发生顺序的示例。obs_3

使用嵌套的 ConcatMapobs_2并且obs_3是同一内部 observable ( inner2) 的一部分,因此仅在第 1 个(包含 1st 、 1st 、 2nd )完成inner2后订阅第 2 个。使用 Sequential ConcatMap ,一旦第一个完成,就会订阅第二个。inner2obs_2obs_3obs_3obs_2obs_2

obs_1: --11--12|
obs_2: --21--22|
obs_3: --31--32|

// Nested ConcatMap
   ❶
--11--12|~~~~~~~~~~~~~~~~~12
   │                       └--21--22|~~~22
   │                           │         └--31--32|
   │        ❷             ❸    └--31--32|
   └--21--22|~~~22        |
       │         └--31--32|    
       └--31--32|              

output: --31--32----31--32--------31--32----31--32|


// Sequential ConcatMap
   ❶
--11--12|~~~12
   │         └--21--22|~~~21~~~~~~~~22
   │                       │         └--31--32|
   │        ❷              └--31--32|
   └--21--22|~~~22        ❸
       │         └--31--32|
       └--31--32|

output: --31--32----31--32----31--32----31--32|


x~~~x    x is emitted at the first position but concatMap is holding the value 
    └O   back and waits with ~ until a previous observable completes and then 
         maps the value to the observable O.
❶        start of the 1st obs_2. For Nested ConcatMap this also marks the start of 
         the 1st inner2.

❷        The 1st obs_2 completed but the 1st inner2 hasn't completed yet.
         Nested ConcatMap waits until the 1st inner2 completes before it maps 12 to 
         the 2nd inner2. Sequential ConcatMap will map 12 to the 2nd obs_2 straight away. 

❸        The 1st inner2 completed. Nested ConcatMap maps 12 to the 2nd inner2.
         Sequential ConcatMap has already mapped 12 to the 2nd obs_2 by this time
         and this 2nd obs_2 has already emitted both values and completed but concatMap
         has buffered those values until now.

如您所见,Sequential ConcatMap 方法obs_2比 Nested ConcatMap 方法更早地订阅了第二个 observable。

于 2021-01-19T11:15:36.983 回答