【发布时间】:2020-12-22 23:11:59
【问题描述】:
我有一个 foreach 循环,我可能需要一个 http 请求来获取一些信息。我尝试在 foreach 循环中使用 forkjoin 来“使 foreach 循环等待 observables”(在这个例子中只有一个 observables,但实际上我会有更多......)。但是有了这段代码,foreach 每个都继续运行,而无需等待可观察对象完成,我找不到任何解决方案来防止这种情况发生。
非常感谢您的帮助!!!
...
let wishes: Wish[] = [];
response.wishes.forEach((wish) => {
let newWish : Wish = new Wish( wish._id, wish.title, wish.price );
let personObservables: Observable<any>[] = [];
if (wish.reservation){
personObservables.push(this.peopleService.getPersonById(wish.reservation.reservedBy));
} else {
personObservables.push(of(null));
}
forkJoin(personObservables).subscribe( ([reservedBy]) => {
if (reservedBy) {
newWish.reservation = {
...wish.reservation,
reservedBy
};
}
wishes.push(newWish);
} );
});
...
编辑:没有 foreach 循环的完整工作解决方案。在管道和数组上的映射函数中使用映射运算符要容易得多。我了解到,将这种逻辑拆分为多个运算符更容易,而不是尝试在 1 个地图运算符中修复它...
public getWishlist ( receiver : Person) : Observable<Wish[]> {
return this.http$.get<IWishlistResponse[]>(
environment.apiUrl + 'wishlist/' + receiver.id
).pipe(
// Create wish instances from each wish in API response and save reservation for later use
map( wishlistResponse =>
wishlistResponse[0].wishes.map(wish => ({
wish: this.createWishInstanceFromResponse(wish, receiver),
reservation: wish.reservation
}))),
// For each wish with reservation: get person info for 'reservedBy' id
map( wishesAndReservationObjects => wishesAndReservationObjects.map( ({wish, reservation}) =>
!reservation ?
of(wish) :
this.peopleService.getPersonById(reservation.reservedBy)
.pipe(
map ( reservedBy => {
if (reservedBy) wish.reservation = {
...reservation,
reservedBy: new Person(reservedBy.id, reservedBy.firstName, reservedBy.lastName)
}
return wish;
})
)
)),
// forkJoin all observables, so the result is an array of all the wishes
switchMap(reservedByObservables => reservedByObservables.length !== 0 ? forkJoin(reservedByObservables) : of(<Wish[]>[])), //https://stackoverflow.com/questions/41723541/rxjs-switchmap-not-emitting-value-if-the-input-observable-is-empty-array
// Call method on each wish (with or without reservation) to set user flags in each instance (must be done after reservedBy is added)
map ( wishes => wishes.map( wish => {
wish.setUserIsFlags(this.userService.currentUser);
return wish;
})),
// For each wish: get state via API call
map ( wishesWithoutState => wishesWithoutState.map( wishWithoutState =>
this.http$.get<wishStatus>(environment.apiUrl + 'wish/' + wishWithoutState.id + '/state')
.pipe(
catchError(() => of(null)),
map( state => {
wishWithoutState.status = state;
return wishWithoutState;
})
)
)),
// Combine all stateObservables into 1 array
switchMap(stateObservables => stateObservables.length !== 0 ? forkJoin(stateObservables) : of(<Wish[]>[]))
)
}
private createWishInstanceFromResponse ( wishResponse : IWishResponse, receiver: Person ) : Wish {
let wish : Wish = new Wish (
wishResponse._id,
wishResponse.title,
wishResponse.price,
...
);
return wish;
}
【问题讨论】:
-
也许完全从循环中删除forkjoin?所以先建数组,再运行fork?
标签: angular foreach rxjs angular2-observables