我有以下代码:
someService.subscribeToChanges().subscribe(value => {
const newValue = someArray.find(val => val.id === value.id)
if (newValue) {
if (value.status === 'someStatus') {
someArray.findIndex((a) => a.id === value.id)
someArray.splice(index, 1);
} else {
newValue.status = value.status;
}
} else {
if (value.someProp === 'abc') {
someService.doSomeAsyncStuff().subscribe(data => {
someService.handleData(data);
});
}
}
});
我想保持相同的逻辑,同时避免第二次订阅。
这是我尝试过的代码
sub$ = someService.subscribeToChanges().pipe(switchMap(value => {
const newValue = someArray.find(val => val.id === value.id)
if (newValue) {
if (value.status === 'someStatus') {
someArray.findIndex((a) => a.id === value.id)
someArray.splice(index, 1);
} else {
newValue.status = value.status;
}
} else {
return iif(() => value.someProp === 'ABC', someService.doSomeAsyncStuff);
}
}));
sub$.subscribe(data => someService.handleData(data))
如果iif
条件为true,则此方法有效,但如果为false,它将停止整个流,而我希望它继续流式传输。
答案 0 :(得分:0)
您可以将它们分为三个条件
sub$ = someService.subscribeToChanges().pipe(switchMap(value => {
const newValue = someArray.find(val => val.id === value.id)
if (newValue) {
if (value.status === 'someStatus') {
someArray.findIndex((a) => a.id === value.id)
someArray.splice(index, 1);
} else {
newValue.status = value.status;
}
return of(value);
}
if(value.someProp === 'ABC')
return someService.doSomeStuff()
return of(value)
})
)
答案 1 :(得分:0)
嵌套订阅是rxjs中的antipattern。因此,您尝试避免它的好处。我建议您仍然使用两个订阅,但不要嵌套。因为您有不同的副作用(someService.handleData和doSomeStuff)
出于重用原因,使用someArray id比较器创建您的subscriptionTochanges ID
const doSomeStuff$ = subscribeToChangesIdEqualsSomeArrayId$.pipe(
filter(newValue => newValue)
);
创建可观察的doSomeStuff
const handleData$ = combineLatest([
subscribeToChangesIdEqualsSomeArrayId$,
someService.subscribeToChanges()
]).pipe(
filter(([newValue, value]) => !newValue && value.someProp === 'abc'),
switchMap(() => someService.doSomeStuff())
);
创建可观察的数据
doSomeStuff$.subscribe(() => doSomeStuff());
handleData$.subscribe(data => someService.handleData(data));
最终用法
{{1}}
仅供参考:我使用了您在问题中使用的所有外部和内部变量名称(从管道角度来看)。我可能会为了阅读而调整它们:)
答案 2 :(得分:-1)
将所有逻辑保持在一个链中总是总好得多,因此您可以像这样进行操作。由于您不需要newValue
,因此非常简单:
someService.subscribeToChanges()
.pipe(
switchMap(value => {
const newValue = someArray.find(val => val.id === value.id);
if (!newValue && value.someProp === 'abc') {
return someService.doSomeStuff();
}
return of(undefined);
}),
)
.subscribe(data => {
if (data === undefined) { // When data is set means we ran the second Observable
doSomeStuff();
} else {
someService.handleData(data);
}
});
如果对于someService.doSomeStuff()
是undefined
的有效响应,那么我将其响应包裹在诸如{ response: data }
之类的对象上,以便您始终知道它的来源。
请尽量避免进行多次订阅,直到真正必要时为止,因为这样做会带来更多您必须了解的事情(例如订阅顺序,共享Observable等等),并且始终容易以自上而下的顺序读取RxJS链,例如这是同步代码。