【问题标题】:Angular/RXJS nested observables using the response from the first call in the second two callsAngular/RXJS 嵌套 observables 使用后两个调用中第一个调用的响应
【发布时间】:2020-07-27 08:18:03
【问题描述】:

我有一个创建返回 Observable 的电影的 POST 请求,该请求的结果返回给我一个 ID,我需要使用该 ID 发出两个进一步的请求以添加导演和电影图像。

我有以下调用,它在添加 Director 时效果很好,但是当我到达第二个 flatMap 时,我无法在不添加订阅的情况下循环遍历图像以发布它们。

有没有更好的方法来做到这一点?我已经尝试过 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)
      }
    })

【问题讨论】:

  • flatMap 解析从回调返回的 observable,但您的回调返回一个 array。你需要例如forkJoin 将一个 observables 数组变成一个 observable 数组。
  • 如果你的 rxjs 代码中有多个“订阅” - 你肯定做错了什么
  • @Andrei 不是一个很有帮助的评论。

标签: angular post rxjs subscribe


【解决方案1】:

假设您要保存导演和图像,并且必须在我保存另一部电影之前完成两个调用,我会这样处理

 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)
      }
    })

我使用 concatMap 的原因是我想等待内部 api 完成后再进行另一个调用。

forkJoin:我希望两个内部 API 都完成。

【讨论】:

    【解决方案2】:

    将您的数组转换为可观察数组并在forkJoin 中运行它们

    flatMap((director: Director) => {
        return forkJoin(movieImages.map((image) => {
          return this.movieRepository.addMovieImage(image, director.movie_id)
        }));
    })
    

    【讨论】:

      【解决方案3】:

      好问题;

      也许您需要正确编排操作,为此您可以使用 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));
      

      您也可以使用 switchMap 代替 concatMap。 如果您需要更多关于如何编排操作的信息,我推荐以下文章:Clean the operators's chain in RxJS

      您好,希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多