[英]Angular/RXJS nested observables using the response from the first call in the second two calls
I have a POST request to create a Movie that returns an Observable, the result of this request returns me an ID that I need to make two further requests using this ID to add a Director & Movie Images.我有一个 POST 请求来创建一个返回 Observable 的电影,这个请求的结果返回一个 ID,我需要使用这个 ID 发出两个进一步的请求来添加一个导演和电影图像。
I have the following call, it works perfectly when it comes to adding the Director however when I get to the second flatMap I'm unable to loop through the images to POST them without adding a subscribe on the end.我有以下调用,它在添加 Director 时完美运行,但是当我到达第二个 flatMap 时,我无法在不添加订阅的情况下循环遍历图像以发布它们。
Is there a better way to do this?有一个更好的方法吗? I have tried switchMap, mergeMap and map but I cannot get the second request to fire without the subscribe.
我已经尝试过 switchMap、mergeMap 和 map,但如果没有订阅,我无法触发第二个请求。
this.Movie.createMovie(movie).pipe(
map((movie: Movie) => {
return movie;
}),
switchMap((movie: Movie) => this.movieRepository.postDirector(director, movie.id)),
flatMap((director: Director) => {
return movieImages.map((image) => {
return this.movieRepository.addMovieImage(image, director.movie_id).subscribe()
});
})
).subscribe({
next: (response: any) => {
console.log(response)
}
})
Assuming you want to save director and the image and both calls must be finished before I save another movie, I would have approached it this way假设您要保存导演和图像,并且必须在我保存另一部电影之前完成两个调用,我会以这种方式处理它
this.Movie.createMovie(movie).pipe(
concatMap((movie: Movie) => {
const saveDirectory$ = this.movieRepository.postDirector(director, movie.id);
const saveMovieImage$ = this.movieRepository.addMovieImage(image, director.movie_id);
return forkJoin(saveDirectory$, saveMovieImage$).pipe(map(([directoryAPIresponse, imageApiResponse])=>{
// you can check if the both records created based on your api response;
return of(true);
}));
)).subscribe({
next: (response: any) => {
console.log(response)
}
})
The reason I use concatMap because I want to wait for inner apis to complete before I make another call.我使用 concatMap 的原因是我想在进行另一个调用之前等待内部 api 完成。
forkJoin: I want both inner APIs to complete. forkJoin:我希望两个内部 API 都完成。
Convert your array to an array of observable and run them in forkJoin
将您的数组转换为可观察数组并在
forkJoin
中运行它们
flatMap((director: Director) => {
return forkJoin(movieImages.map((image) => {
return this.movieRepository.addMovieImage(image, director.movie_id)
}));
})
Great question;好问题;
Maybe what you need is to properly orchestrate the operations, for which you can use Tuples(pair) and a more ordered code like this:也许您需要的是正确编排操作,为此您可以使用 Tuples(pair) 和更有序的代码,如下所示:
this.Movie.createMovie(movie)
.pipe(
concatMap(movie => this.movieRepository.postDirector(director, movie.id).pipe(map(director => [movie, director]))),
concatMap(pair => this.movieRepository.addMovieImage((pair[0] as Movie).image, (pair[1] as Director).movie_id))
)
.subscribe(response => console.log(response));
You can also use switchMap instead of a concatMap .您也可以使用switchMap代替concatMap 。 If you need more information on how to orchestrate operations, I recommend the following article: Clean the operators's chain in RxJS .
如果您需要更多关于如何编排操作的信息,我推荐以下文章: 清理 RxJS 中的操作员链。
Greetings, I hope I have helped.您好,希望对您有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.