Javascript RxJs中按属性区分的开关映射
比方说,我有一连串的行动。每个操作都分配了一些id。如下所示:Javascript RxJs中按属性区分的开关映射,javascript,rxjs,ngrx,redux-observable,switchmap,Javascript,Rxjs,Ngrx,Redux Observable,Switchmap,比方说,我有一连串的行动。每个操作都分配了一些id。如下所示: const actions$ = of({ id: 1 }, { id: 2 }, { id: 1 }); 现在,对于每个动作,我想在switchMap中执行一些逻辑: actions$.pipe(switchMap(a => /* some cancellable logic */)).subscribe(...); 问题是,每个发出的操作都会取消以前的“某些可取消逻辑” 是否可以根据操作id(最好是操作员)取消“某些可
const actions$ = of({ id: 1 }, { id: 2 }, { id: 1 });
现在,对于每个动作,我想在switchMap中执行一些逻辑:
actions$.pipe(switchMap(a => /* some cancellable logic */)).subscribe(...);
问题是,每个发出的操作都会取消以前的“某些可取消逻辑”
是否可以根据操作id(最好是操作员)取消“某些可取消逻辑”?比如:
actions$.pipe(switchMapBy('id', a => /*some cancellable logic */)).subscribe(...)
本质上,switchMap的当前行为:
1.动作$emits id 1。switchMap订阅嵌套的observable。
2.动作$emits id 2。switchMap取消订阅以前嵌套的observable。订阅新的。
3.动作$emits id 1。switchMap再次取消订阅以前嵌套的observable。订阅新的
预期行为:
1.动作$emits id 1。switchMap订阅嵌套的observable。
2.动作$emits id 2。switchMap再次订阅嵌套的observable,这次是2。这里的区别是,它不会抵消1中的一个。
3.动作$emits id 1。switchMap从嵌套的observable取消订阅1。再次订阅,例如1。在switchMap之前使用filter操作排除已取消的ID,如下所示
of({ id: 1 }, { id: 2 }, { id: 1 }).pipe(
filter(id => ![1,2].includes(id)), // to exclude ids (1,2)
switchMap(id => /*some cancellable logic */ )
).subscribe(...)
在switchMap之前使用filter操作排除取消的ID,如下所示
of({ id: 1 }, { id: 2 }, { id: 1 }).pipe(
filter(id => ![1,2].includes(id)), // to exclude ids (1,2)
switchMap(id => /*some cancellable logic */ )
).subscribe(...)
这似乎是mergeMap操作符的一个用例。switchMap的用例是只维护一个内部订阅并取消以前的订阅,这不是您想要的。您需要多个内部订阅,并且希望在通过相同id的新值时取消这些订阅,因此实现一些自定义逻辑来实现这一点 大致如下:
action$.pipe(
mergeMap(val => {
return (/* your transform logic here */)
.pipe(takeUntil(action$.pipe(filter(a => a.id === val.id)))); // cancel it when the same id comes back through, put this operator at the correct point in the chain
})
)
您可以通过编写自定义运算符将其转换为可恢复的内容:
import { OperatorFunction, Observable, from } from 'rxjs';
import { takeUntil, filter, mergeMap } from 'rxjs/operators';
export function switchMapBy<T, R>(
key: keyof T,
mapFn: (val: T) => Observable<R> | Promise<R>
): OperatorFunction<T, R> {
return input$ => input$.pipe(
mergeMap(val =>
from(mapFn(val)).pipe(
takeUntil(input$.pipe(filter(i => i[key] === val[key])))
)
)
);
}
下面是一个闪电战:这似乎是mergeMap操作符的一个用例。switchMap的用例是只维护一个内部订阅并取消以前的订阅,这不是您想要的。您需要多个内部订阅,并且希望在通过相同id的新值时取消这些订阅,因此实现一些自定义逻辑来实现这一点 大致如下:
action$.pipe(
mergeMap(val => {
return (/* your transform logic here */)
.pipe(takeUntil(action$.pipe(filter(a => a.id === val.id)))); // cancel it when the same id comes back through, put this operator at the correct point in the chain
})
)
您可以通过编写自定义运算符将其转换为可恢复的内容:
import { OperatorFunction, Observable, from } from 'rxjs';
import { takeUntil, filter, mergeMap } from 'rxjs/operators';
export function switchMapBy<T, R>(
key: keyof T,
mapFn: (val: T) => Observable<R> | Promise<R>
): OperatorFunction<T, R> {
return input$ => input$.pipe(
mergeMap(val =>
from(mapFn(val)).pipe(
takeUntil(input$.pipe(filter(i => i[key] === val[key])))
)
)
);
}
这里有一个闪电战:你想要的是什么还不清楚,我会尝试添加一些你正在寻找的行为的具体例子。我最好学画大理石图。现在清楚多了。看起来你更喜欢合并地图,我不确定。当第二次发出id为1的操作时,mergeMap不会取消上一个操作。您需要一些自定义逻辑来取消其他订阅,它不会自动执行此操作,尝试提出解决方案时,mergeScan可能更适合这种情况。您要做的是相当不清楚,我会尝试添加一些你正在寻找的行为的具体例子。我最好学画大理石图。现在清楚多了。看起来你更喜欢合并地图,我不确定。当第二次发出id为1的操作时,mergeMap不会取消上一个操作。您需要一些自定义逻辑来取消其他订阅,它不会自动执行,试图找到解决方案,mergeScan可能更适合这种情况。谢谢!这就是我需要的。我想我将把它隐藏在自定义操作符后面,因为它将在几个地方使用。我添加了一个示例,说明如何将我的解决方案转换为可恢复的自定义switchMapBy操作符库!这就是我需要的。我想我将把它隐藏在自定义操作符后面,因为它将在几个地方使用。我添加了一个示例,说明如何将我的解决方案转换为可恢复的自定义switchMapBy操作符