RXJS - 嵌套 concapMap 是否等同于顺序 concatMap?
RXJS - Are nested concapMap equivalent to sequential concatMap?
当使用 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 的方式被认为是等效的(例如,关于失败)?
感谢任何帮助...
不,它们在所有情况下的行为方式不同。
嵌套 ConcatMap
observable1.pipe(
concatMap(result1 => inner2)
)
inner2 = observable2.pipe(
concatMap(result2 => observable3.pipe(
concatMap(result3 => of(result3))
))
))
将在前一个 inner2
observable 完成时将下一个值从 observable1
映射到 inner2
。
顺序 ConcatMap
observable1.pipe(
concatMap(result1 => observable2),
concatMap(result2 => observable3),
concatMap(result3 => of(result3))
)
将在前一个 observable2
完成后将下一个值从 observable1
映射到 observable2
。
您在最终订阅回调中收到的结果将是相同的,并且会以相同的顺序到达。但是您收到这些结果的时间可能会有所不同,因为 Nested ConcatMap 中的 observable 可能会比 Sequential ConcatMap 中的 observable 晚映射到后续 inner2
observable 将映射到后续的 observable2
observables,因为 inner2
可能比 observable2
.
需要更长的时间才能完成
例子
使用三个可观察值 obs_1
、obs_2
和 obs_3
的事件发生顺序示例:https://stackblitz.com/edit/rxjs-mxfdtn?file=index.ts.
With Nested ConcatMap obs_2
和 obs_3
是同一内部可观察对象 (inner2
) 的一部分,因此第二个 inner2
仅在第一个 inner2
(包含第一个obs_2
、第一个obs_3
、第二个obs_3
)完成。使用 Sequential ConcatMap,第二个 obs_2
在第一个 obs_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 方法比 Nested ConcatMap 方法更早订阅第二个 obs_2
observable。
当使用 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 的方式被认为是等效的(例如,关于失败)?
感谢任何帮助...
不,它们在所有情况下的行为方式不同。
嵌套 ConcatMap
observable1.pipe(
concatMap(result1 => inner2)
)
inner2 = observable2.pipe(
concatMap(result2 => observable3.pipe(
concatMap(result3 => of(result3))
))
))
将在前一个 inner2
observable 完成时将下一个值从 observable1
映射到 inner2
。
顺序 ConcatMap
observable1.pipe(
concatMap(result1 => observable2),
concatMap(result2 => observable3),
concatMap(result3 => of(result3))
)
将在前一个 observable2
完成后将下一个值从 observable1
映射到 observable2
。
您在最终订阅回调中收到的结果将是相同的,并且会以相同的顺序到达。但是您收到这些结果的时间可能会有所不同,因为 Nested ConcatMap 中的 observable 可能会比 Sequential ConcatMap 中的 observable 晚映射到后续 inner2
observable 将映射到后续的 observable2
observables,因为 inner2
可能比 observable2
.
例子
使用三个可观察值 obs_1
、obs_2
和 obs_3
的事件发生顺序示例:https://stackblitz.com/edit/rxjs-mxfdtn?file=index.ts.
With Nested ConcatMap obs_2
和 obs_3
是同一内部可观察对象 (inner2
) 的一部分,因此第二个 inner2
仅在第一个 inner2
(包含第一个obs_2
、第一个obs_3
、第二个obs_3
)完成。使用 Sequential ConcatMap,第二个 obs_2
在第一个 obs_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 方法比 Nested ConcatMap 方法更早订阅第二个 obs_2
observable。