简体   繁体   English

Angular/RXJS 嵌套 observables 使用后两个调用中第一个调用的响应

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM