我需要获得一个包含产品数组的订单。但是getProduct()的工作时间比我需要的晚,并且所有产品都未定义。我发现嵌套订阅是不好的方式,那么使用mergeMap/switchMap
的正确方法是什么?getOrder(id: string) {
this.orderService
.getOrder(id)
.subscribe(order => {
order.map(item => {
data.push(item.payload.doc.data());
return data;
});
this.order = data[0].products.map(x => this.getProduct(x))
});
}
getProduct(id: string) {
return this.productService
.getProduct(id)
.subscribe(product => product);
}
getOrderById(id: string): Observable < any > {
return this.afs
.collection('orders', ref => ref.where('uid', '==', id))
.snapshotChanges();
}
getProductById(id: string): Observable < any > {
return this.afs
.collection('products', ref => ref.where('uid', '==', id))
.valueChanges();
}
我看到这里有两个相互独立的可观测值
- getOrderById() 2) getProductById()
你可以合并这两个可观察对象,并且只订阅一次,也可以取消订阅。像这样:
const orderByIdObservable = this.getOrderById();
const productByIdObservable = this.getProductById();
destroy$: Subject<any> = new Subject(); // This is used to destroy the subscription later
************************************************************
*********** Using 'combineLatest' RXJS operator **********
************************************************************
// Combine the observables and destroy once done, in 1 shot.
combineLatest(orderByIdObservable,productByIdObservable)
.pipe(
takeUntil(this.destroy$),
take(1)
)
.subscribe(
([orderByIdObservableData, productByIdObservableData]) => {
if (orderByIdObservableData && productByIdObservableData) {
// do your logic here
}
}
);
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
A) combineLatest - will combine all the observables and subscribe only once
B) takeUntil - this will keep subscribing until the destroy$ is completed/closed
C) take(1) - this will always take only the first value. You may or may not want to keep this
D) destroy$ - Use the Subject variable to destroy the service one the component is destroyed
************************************************************
*********** Using 'mergeMap' RXJS operator **********
************************************************************
orderByIdObservable
.pipe(
mergeMap(productIdObsData => productByIdObservable.pipe(tap(data => !!data)),
takeUntil(this.destroy$),
take(1)
)
.subscribe(data => {
console.log('Both the data merged into one', data);
// here both the observables data are merged into one data variable
})
A) mergeMap - if the data of the first observable is successfully subscribed, then only this mergeMap works otherwise the data after merging and subscribing is either null, undefined or some random object.
B) takeUntil - this will keep subscribing until the destroy$ is completed/closed
C) take(1) - this will always take only the first value. You may or may not want to keep this
D) destroy$ - Use the Subject variable to destroy the service one the component is destroyed
与mergeMap相比,combinellatest的优点是您将只有一个订阅和一个取消订阅,而在mergeMap中,您将有两个。