NgRx 效果 mergeMap 方法
NgRx effect mergeMap approach
我有两个相同效果的实现,都有效。我很难理解两者之间的区别,哪个更 "correct".
请在下面找到它们:
选项 1。IDE 无法确定最后一个 map
中 instance
的类型。
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(action => action.instances),
map(instance => performRequest({ instance }))
)
);
选项 2。所有类型都有效且有意义。这对我来说更正确,但我想找出并理解其中的差异。
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(({ instances }) =>
instances.map(instance => performRequest({ instance }))
)
)
);
有一个很好的指南 here 好的和坏的做法。
考虑你的第二个例子。如果您想在第二张地图中添加另一张地图怎么办?
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(({ instances }) =>
instances.map(instance => performRequest({
instance.map(() => { // And another map})
}))
)
)
);
这很快会使您的代码变得难读。错误处理如何?
在您的第一个示例中,您可以只添加一个适用于所有地图的 catchError。在第二种情况下,您需要为那里的每张地图做一个错误处理。
// VERY BAD: nesting subscribes is ugly and takes away
// the control over a stream
这同样适用于映射,以及任何其他应通过管道传输的运算符。管道运算符相当于 linux 管道 |,被认为是最佳实践。它提供了更简洁的代码。
对于其中的几个可能没有意义,但是当它嵌套在多个级别时,它会变得非常讨厌并且代码变得不可读。
我最近做了一个重构,让状态 2 看起来像一个大项目中的状态,这样我就可以更好地管理代码。
看来第一种方法应该不行:
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(action => action.instances),
map(instance => performRequest({ instance }))
)
);
mergeMap
在这种情况下使您的数组变平,并且 map
returns 每个发射值的 Observablve。最后你会得到一个 Observable of Observables (Observable<Observable<your type>>
)。您需要使用 Higher Order Observables 之一而不是 map
才能使其正常工作。
第二个选项正确:
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(({ instances }) =>
instances.map(instance => performRequest({ instance }))
)
)
);
在这种情况下,mergeMap
将 instances.map
生成的一组可观察值合并为一个可观察值。
使用这种方法的好处是您可以控制可观察对象,您可以将 catchError
应用于每个 performRequest
或在 mergeMap
之后将其应用于更高级别,以便对所有对象进行单一错误处理performRequest
调用。
我有两个相同效果的实现,都有效。我很难理解两者之间的区别,哪个更 "correct".
请在下面找到它们:
选项 1。IDE 无法确定最后一个 map
中 instance
的类型。
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(action => action.instances),
map(instance => performRequest({ instance }))
)
);
选项 2。所有类型都有效且有意义。这对我来说更正确,但我想找出并理解其中的差异。
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(({ instances }) =>
instances.map(instance => performRequest({ instance }))
)
)
);
有一个很好的指南 here 好的和坏的做法。
考虑你的第二个例子。如果您想在第二张地图中添加另一张地图怎么办?
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(({ instances }) =>
instances.map(instance => performRequest({
instance.map(() => { // And another map})
}))
)
)
);
这很快会使您的代码变得难读。错误处理如何?
在您的第一个示例中,您可以只添加一个适用于所有地图的 catchError。在第二种情况下,您需要为那里的每张地图做一个错误处理。
// VERY BAD: nesting subscribes is ugly and takes away // the control over a stream
这同样适用于映射,以及任何其他应通过管道传输的运算符。管道运算符相当于 linux 管道 |,被认为是最佳实践。它提供了更简洁的代码。
对于其中的几个可能没有意义,但是当它嵌套在多个级别时,它会变得非常讨厌并且代码变得不可读。
我最近做了一个重构,让状态 2 看起来像一个大项目中的状态,这样我就可以更好地管理代码。
看来第一种方法应该不行:
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(action => action.instances),
map(instance => performRequest({ instance }))
)
);
mergeMap
在这种情况下使您的数组变平,并且 map
returns 每个发射值的 Observablve。最后你会得到一个 Observable of Observables (Observable<Observable<your type>>
)。您需要使用 Higher Order Observables 之一而不是 map
才能使其正常工作。
第二个选项正确:
pollingStarted$ = createEffect(() =>
this.actions$.pipe(
ofType(pollingStarted),
mergeMap(({ instances }) =>
instances.map(instance => performRequest({ instance }))
)
)
);
在这种情况下,mergeMap
将 instances.map
生成的一组可观察值合并为一个可观察值。
使用这种方法的好处是您可以控制可观察对象,您可以将 catchError
应用于每个 performRequest
或在 mergeMap
之后将其应用于更高级别,以便对所有对象进行单一错误处理performRequest
调用。