【问题标题】:How to await rxjs Observable without changing all the code to promises如何在不将所有代码更改为 Promise 的情况下等待 rxjs Observable
【发布时间】:2019-06-05 21:53:24
【问题描述】:

是否可以在不更改为 Promises 的情况下等待可观察的 rxjs? 我正在执行 6 个请求 OnInit() 但是,一些请求在另一个请求之前完成,顺序很重要。是否可以在 typecrypt 中等待 observable?所有功能看起来都一样,它们只是向服务器发出不同的请求。 谢谢您的帮助 :) 这是我的代码:

我设法通过链接请求来实现它(在我得到前一个请求的响应后调用下一个请求,但是,该解决方案效率不高而且看起来很丑)

 ngOnInit() {
      this.userId = this.auth.getUserId();

      this.getTrendingRentals();
      this.getFollowingRentals();
      ...
      this.getLuxuryRentals();
      //console.log(this.totalRentals);
    }

    private getTrendingRentals() {
        const rentalObservable = this.rentalService.getRentals();
        //Subscribe to service observer
        rentalObservable.subscribe((rentals: Rental[]) => {
          this.trendingRentals = rentals;
          this.totalRentals.push(this.trendingRentals);
        }, (err) => {
        }, () => {
      });
    }


    public getLuxuryRentals(): Observable<any>{
      return this.http.get('/api/v1/rentals/luxury');
    }

【问题讨论】:

    标签: angular typescript asynchronous async-await rxjs


    【解决方案1】:

    你可以在管道中使用switchMap,以便在后续的observable中使用第一个observable的结果。

    of("Hello").pipe(
                switchMap(result => of(result + ", World")),
                switchMap(result => of(result + "!")),
              )
              .subscribe(console.log);
    // output: Hello, World!
    

    但如果您不需要前一个 observable 的结果,而只想按特定顺序触发 observable,则可以使用 concat 等待每个 observable 完成后再触发下一个 observable:

    concat(
      of(1).pipe(delay(2000)),
      of(2).pipe(delay(500)),
      of(3).pipe(delay(1000))
    )
    .subscribe(console.log);
    
    // output: 1 2 3
    

    【讨论】:

    • 感谢您的回答!!即使延迟较小,of(2).pipe(delay(500)) 如何在 of(1).pipe(delay(2000)) 之后完成?
    • concat 在触发下一个 observable 之前等待第一个 observable 完成。所以将 observable 放入 concat 函数的顺序是相关的。
    【解决方案2】:

    获取数据的方法不应返回订阅,而是返回可观察对象,

    private getTrendingRentals() {
        return this.rentalService.getRentals();
    }
    

    rxjs 提供了很少的函数来解决这类问题。看看函数:mergemergeMapswitchMapconcatMap

    例如:

    this.auth.getUserId().pipe(
          mergeMap(userId => this.getTrendingRentals()),
          mergeMap(trendingRentals => this.getFollowingRentals()),
          mergeMap(followingRentals => this.getFollowingRentals()),
          mergeMap(luxuryRentals => this.getLuxuryRentals())
    ).subscribe(...)
    

    this.auth.getUserId().pipe(
          mergeMap(userId => this.getTrendingRentals()),
          mergeMap(trendingRentals => merge(this.getFollowingRentals(), this.getFollowingRentals(), this.getLuxuryRentals()))
    ).subscribe(...)
    

    取决于您的特定需求。

    更新: 带有concat 的@jcal 解决方案看起来更好:)

    【讨论】:

    • 感谢您的回答!!我对 this.auth.getUserId().pipe(mergeMap(userId => this.getTrendingRentals()), userId 是第一个函数的结果感到困惑?就像普通的回调一样?我是 rxjs 的新手,所以我只是假设。
    • merge 并不真正属于该列表
    猜你喜欢
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    • 2018-02-19
    • 1970-01-01
    相关资源
    最近更新 更多