我有一个名为fetchSeviceProviders的函数,该函数将向我返回服务提供商的列表,并让我通过调用其他服务来设置服务提供商的徽标。我通过使用两个订阅实现了这一点。
在第一次订阅时,我得到了列表。然后,我将其映射并通过所有服务提供商的ID调用fetchServiceProviderLogo。
可以通过一个订阅完成此操作吗?我的方法可以吗?如果没有,那是什么问题?一些rxjs运算符如何执行此操作?
我尝试了map和flatMap运算符,但没有任何线索。
fetchServiceProviders ()
{
this.subscribers.fetchServiceProvidersLogoSub = this.serviceProviderService.fetchServiceProviders( new Map() ).subscribe(
data =>
{
this.providers = data._embedded.serviceProviders;
this.providers.map(
provider =>
{
this.subscribers.fetchServiceProvidersLogoSub =
this.serviceProviderService.fetchServiceProviderLogo( { 'id': provider.id } ).subscribe(
logo =>
{
this.createIndividualLogoFromBlob( provider, logo );
}
);
}
);
}
)
}
答案 0 :(得分:1)
如果所有可观测对象都已完成并且this.serviceProviderService.fetchServiceProviderLogo
的调用顺序无关紧要,则可以组合使用switchMap
(或mergeMap
)和merge
。如果您的提取请求全部完成,您也不必取消订阅。
fetchServiceProviders () {
this.serviceProviderService.fetchServiceProviders(new Map())
.pipe(
map(data => data._embedded.serviceProviders),
mergeMap(providers => merge(
providers.map(provider =>
this.serviceProviderService.fetchServiceProviderLogo({ 'id': provider.id })
.pipe(map(logo => ({ provider, logo })))
)
))
)
.subscribe(({ provider, logo }) => this.createIndividualLogoFromBlob(provider, logo));
}
您可以使用merge
而不是forkJoin
来并行执行this.serviceProviderService.fetchServiceProviderLogo
调用。
fetchServiceProviders () {
this.serviceProviderService.fetchServiceProviders(new Map())
.pipe(
map(data => data._embedded.serviceProviders),
mergeMap(providers => forkJoin(
providers.map(provider =>
this.serviceProviderService.fetchServiceProviderLogo({ 'id': provider.id })
.pipe(map(logo => ({ provider, logo })))
)
))
)
.subscribe(providerLogos =>
providerLogos.forEach(({ provider, logo }) => this.createIndividualLogoFromBlob(provider, logo))
);
}
答案 1 :(得分:0)
在您的代码中,您正在为每个serviceProvider进行预订。 如果您想一次完成所有操作,则可以查看合并运算符:https://www.learnrxjs.io/operators/combination/merge.html
答案 2 :(得分:0)
这是一个简单的例子。您可以考虑getItems
和getStreetNameById
您的提供商。
import { of, from } from 'rxjs';
import { switchMap, groupBy, map, mergeMap } from 'rxjs/operators';
function getItems() {
return of([
{ streetId: 1, person: 'Person 1' },
{ streetId: 2, person: 'Person 2' },
{ streetId: 1, person: 'Person 3' },
]);
}
function getStreetNameById(id: number) {
console.log('requesting street name for ', id);
return of('Street ' + id);
}
getItems().pipe( //get all the items
switchMap(items => from(items)), //create a new stream with each item from the list
groupBy(item => item.streetId), //group by the streetId (we want to request the street name once per id
mergeMap(group => { //merge all the transformed groups back into one stream
return getStreetNameById(group.key) //request the street name by id
.pipe(
switchMap(streetName => group.pipe( //merge the street name back to all the items in the group
map(item => ({ ...item, streetName })),
))
);
})
).subscribe(items => {
console.log(items); //now all the items have the street name
});
https://stackblitz.com/edit/rxjs-merge-providers?file=index.ts