我发现自己很困惑,试图设置一个非常简单的rxjs订阅流程。将多个不相关的订阅嵌套到另一个订阅中。
我正在使用角度应用程序,在进行其他订阅之前,我需要先填充下一个主题。
这里是我想要实现的嵌套版本。
subject0.subscribe(a => {
this.a = a;
subject1.subscribe(x => {
// Do some stuff that require this.a to exists
});
subject2.subscribe(y => {
// Do some stuff that require this.a to exists
});
});
我知道嵌套订阅不是一个好习惯,我尝试使用flatMap
或concatMap
,但并没有真正了解如何实现。
答案 0 :(得分:1)
您可以使用concat
运算符来实现。
const first = of('first').pipe(tap((value) => { /* doSomething */ }));
const second = of('second').pipe(tap((value) => { /* doSomething */ }));
const third = of('third').pipe(tap((value) => { /* doSomething */ }));
concat(first, second, third).subscribe();
通过这种方式,一切都按照定义的顺序链接和执行。
编辑
const first = of('first').pipe(tap(value => {
// doSomething
combineLatest(second, third).subscribe();
}));
const second = of('second').pipe(tap(value => { /* doSomething */ }));
const third = of('third').pipe(tap(value => { /* doSomething */ }));
first.subscribe();
这样,second
和third
会在first
发出后立即异步运行。
答案 1 :(得分:1)
您可以执行以下操作:
subject$: Subject<any> = new Subject();
this.subject$.pipe(
switchMap(() => subject0),
tap(a => {
this.a = a;
}),
switchMap(() => subject1),
tap(x => {
// Do some stuff that require this.a to exists
}),
switchMap(() => subject2),
tap(y => {
// Do some stuff that require this.a to exists
})
);
如果要触发此操作,只需调用this.subject $ .next();
编辑: 这是forkJoin的一种可能方法,该方法将主题并行调用。
subject$: Subject<any> = new Subject();
this.subject$.pipe(
switchMap(() => subject0),
tap(a => {
this.a = a;
}),
switchMap(
() => forkJoin(
subject1,
subject2
)),
tap([x,y] => {
// Do some stuff that require this.a to exists
})
);
答案 2 :(得分:1)
每个Observable分离数据流总是一个好主意,这样以后您就可以轻松地将它们组合起来。
const first$ = this.http.get('one').pipe(
shareReplay(1)
)
shareReplay
用于使Observable hot 处于可热状态,因此每次订阅都不会调用http.get('one')
。
const second$ = this.first$.pipe(
flatMap(firstCallResult => this.http.post('second', firstCallResult))
);
const third$ = this.first$.pipe(
flatMap(firstCallResult => this.http.post('third', firstCallResult))
);
此后,您可以订阅所需的Observable:
second$.subscribe(()=>{}) // in this case two requests will be sent - the first one (if there were no subscribes before) and the second one
third$.subscribe(() => {}) // only one request is sent - the first$ already has the response cached
如果您不想将first$
的值存储在任何地方,只需将其转换为:
this.http.get('one').pipe(
flatMap(firstCallResult => combineLatest([
this.http.post('two', firstCallResult),
this.http.post('three', firstCallResult)
])
).subscribe(([secondCallResult, thirdCallResult]) => {})
还可以使用BehaviorSubject
将值存储在其中:
const behaviorSubject = new BehaviorSubject<string>(null); // using BehaviorSubject does not require you to subscribe to it (because it's a hot Observable)
const first$ = behaviorSubject.pipe(
filter(Boolean), // to avoid emitting null at the beginning
flatMap(subjectValue => this.http.get('one?' + subjectValue))
)
const second$ = first$.pipe(
flatMap(firstRes => this.http.post('two', firstRes))
)
const third$ = first$.pipe(
flatMap(()=>{...})
)
behaviorSubject.next('1') // second$ and third$ will emit new values
behaviorSubject.next('2') // second$ and third$ will emit the updated values again