[英]How to combine observables in a non-blocking way?
我有一个Observable集合,每个Observable都检索不同的数据类型。 我正在链接那些Observable来获取我想要的所有数据。 事实是所有这些信息都是独立的,因此加载一个信息不应该阻止或干扰加载其他信息。 这是我无法实现的。
这是我目前所做的一个例子:
getAll(): Observable<any[]> {
return this.getHome().pipe(
tap((home: Home) => this.application = home),
mergeMap((home: Home) =>
combineLatest([
this.getAssets(home.images).pipe(defaultIfEmpty([])),
this.getStyling(home.styling).pipe(defaultIfEmpty({})),
this.getCategories(home.categories).pipe(defaultIfEmpty([])),
])
)
);
}
在这里,Observable被成功链接,所以我得到了我想要的所有数据,但是一旦前一个完成, combineLatest()
会执行下一个请求,并且一旦完成所有内容,父节点就会发出收集的数据,从而产生延迟。 我一直在尝试使用merge()
而不是combineLatest()
以便收到的每个数据立即发送到父Observable,但显然我不能这样做
那么,我如何设法链接那些Observable,以便子Observable中的每个提交直接发送到父Observable?
你需要forkJoin
,它返回一个Array
,其中包含每个Observable
的结果(与forkJoin
参数的顺序相同)。
getAll(): Observable<any[]> {
return this.getHome().pipe(
tap((home: Home) => this.application = home),
mergeMap((home: Home) =>
forkJoin(
this.getAssets(home.images).pipe(defaultIfEmpty([])),
this.getStyling(home.styling).pipe(defaultIfEmpty({})),
this.getCategories(home.categories).pipe(defaultIfEmpty([]))
)
)
);
}
如果它们是独立的,您可以独立处理它们并在主题上发出它们。
getAll(): Observable<any> {
const subject = new Subject<any>();
const handler = (res: any) => subject.next(res);
this.getHome().pipe(
tap((home: Home) => this.application = home),
tap(handler),
tap((home: Home) => {
forkJoin(
this.getAssets(home.images).pipe(defaultIfEmpty([]),tap(handler))
this.getStyling(home.styling).pipe(defaultIfEmpty({}), tap(handler))
this.getCategories(home.categories).pipe(defaultIfEmpty([]), tap(handler))
).subscribe(res => subject.complete())
})
).subscribe();
return subject.asObservable();
}
使用此方法,类型检查必须由使用者完成。
受试者在此记录 。
我一直在尝试使用merge()而不是combineLatest(),以便收到的每个数据立即发送到父Observable,但显然我不能这样做
听起来好像你正在准备好部分数据。 combineLatest()和forkJoin()只有在可以将长度相等的数组填充到可观察数量时才会发出数据。 因此,您要么等待每个observable中的至少一个值,要么等待它们全部完成,但它们会发出一个数组,并且需要知道要放入哪个数组。
我想你想在它准备好后立即发出每一段数据。
首先使用merge()从所有3个observable中发出值,但是对于每个observable使用map()来为该给定类型(图像,样式,类别)创建对象键/值对。
最后,使用scan()运算符将值聚合到单个对象中,该对象将在更新时发出每个属性。
流的消费者可以检查属性是否为null
以查看它是否已准备好。 流将在完成之前发出3个值。
getAll(): Observable<{home: Home, images: any[], styling: any[], categories: any[]}> {
return this.getHome().pipe(
tap((home: Home) => this.application = home),
switchMap((home: Home) =>
merge([
this.getAssets(home.images).pipe(
defaultIfEmpty([]),
map(images => ({images}))
),
this.getStyling(home.styling).pipe(
defaultIfEmpty({}),
map(styling => ({styling}))
),
this.getCategories(home.categories).pipe(
defaultIfEmpty([]),
map(categories => ({categories})
),
]),
scan((acc, next) => ({...acc, ...next}), {home, images: null, styling: null, categories: null})
)
);
}
如果要发出所有属性为null
的第一个值,可以将startWith({})
运算符添加到merge()
运算符。 作为消费者的早期价值,他们知道其他价值的阅读已经开始。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.