在第二个可观察对象中修改第一个可观察对象的结果并 return 更新结果
Modify result of first observable in second observable and return updated result
我有一个方法 exampleMethod()
returns 2 个连续服务调用(getData1()
和 getData2()
)的结果,而 getData2()
必须修改getData1()
在 exampleMethod()
returns 之前返回的数据。目前,嵌套服务调用在我们已经从 exampleMethod()
返回之后执行,但为时已晚。我知道在另一个可观察对象中调用订阅是一种不好的做法,可能会导致问题,所以我想问的是什么是正确的方法。下面的示例代码。谢谢!
exampleMethod() {
return this.myService.getData1()
.pipe(
map(res => {
res.orders = someValue;
return res;
}),
map(res => {
res.orders.forEach((order: any) => {
this.myService.getData2()
.pipe(
tap((orders: any[]) =>
order.status = orders.find(o=> o.number === order.number).status // <<====== this resolves after we've already returned from exampleMethod()
)
).subscribe();
});
return res; // <<====== status value of res.orders not set
})
);
}
你说内部订阅不优雅是对的。您需要 RxJS switchMap
运算符和 forkJoin
函数来处理多个同时请求。
尝试以下方法
exampleMethod(): Observable<any> { // <-- define return type here
return this.myService.getData1().pipe(
map(res => ({...res, res.orders: someValue})),
switchMap(res =>
forkJoin(
res.orders.map(order =>
this.myService.getData2().pipe(map((orders: any[]) => // <-- pip the `map` operator here
({...res, res.status: orders.find(o => o.number === order.number).status})
))
)
)
)
);
}
编辑:为 RxJS map
包含 pipe
您可以使用高阶 Observable 来做到这一点。我怀疑 switchMap
可能不是您要查找的内容,而是 concatMap or concatAll.
return this.myService.getData1().pipe(
map((res) => {
res.orders = ["someValue"];
return res;
}),
map((res) =>
// <-- use switch map to internally subscribe to inner observable
res.orders.forEach((order: any) =>
this.myService.getData2().pipe(
first(),
tap(/* do something */)
);
)
),
concatAll(), // <-- concat all inner-observables values in order
last() // ensure that only the last value is emitted to outer observable
);
不过要记住一件事,可观察对象不会同步发出值。因此,在 observable 处理任何值之前,exampleMethod()
将始终 return。一种方法,尽管我不推荐它,是在异步方法中等待可观察对象的完成:
async function exampleMethod(){
return await this.dataService.getData()
.pipe(/* whatever*/ )
.toPromise(); // this will resolve when the observable is complete
}
我有一个方法 exampleMethod()
returns 2 个连续服务调用(getData1()
和 getData2()
)的结果,而 getData2()
必须修改getData1()
在 exampleMethod()
returns 之前返回的数据。目前,嵌套服务调用在我们已经从 exampleMethod()
返回之后执行,但为时已晚。我知道在另一个可观察对象中调用订阅是一种不好的做法,可能会导致问题,所以我想问的是什么是正确的方法。下面的示例代码。谢谢!
exampleMethod() {
return this.myService.getData1()
.pipe(
map(res => {
res.orders = someValue;
return res;
}),
map(res => {
res.orders.forEach((order: any) => {
this.myService.getData2()
.pipe(
tap((orders: any[]) =>
order.status = orders.find(o=> o.number === order.number).status // <<====== this resolves after we've already returned from exampleMethod()
)
).subscribe();
});
return res; // <<====== status value of res.orders not set
})
);
}
你说内部订阅不优雅是对的。您需要 RxJS switchMap
运算符和 forkJoin
函数来处理多个同时请求。
尝试以下方法
exampleMethod(): Observable<any> { // <-- define return type here
return this.myService.getData1().pipe(
map(res => ({...res, res.orders: someValue})),
switchMap(res =>
forkJoin(
res.orders.map(order =>
this.myService.getData2().pipe(map((orders: any[]) => // <-- pip the `map` operator here
({...res, res.status: orders.find(o => o.number === order.number).status})
))
)
)
)
);
}
编辑:为 RxJS map
pipe
您可以使用高阶 Observable 来做到这一点。我怀疑 switchMap
可能不是您要查找的内容,而是 concatMap or concatAll.
return this.myService.getData1().pipe(
map((res) => {
res.orders = ["someValue"];
return res;
}),
map((res) =>
// <-- use switch map to internally subscribe to inner observable
res.orders.forEach((order: any) =>
this.myService.getData2().pipe(
first(),
tap(/* do something */)
);
)
),
concatAll(), // <-- concat all inner-observables values in order
last() // ensure that only the last value is emitted to outer observable
);
不过要记住一件事,可观察对象不会同步发出值。因此,在 observable 处理任何值之前,exampleMethod()
将始终 return。一种方法,尽管我不推荐它,是在异步方法中等待可观察对象的完成:
async function exampleMethod(){
return await this.dataService.getData()
.pipe(/* whatever*/ )
.toPromise(); // this will resolve when the observable is complete
}