【问题标题】:Angular (4): Multiple HTTP requests with Observables: one after another succeedsAngular(4):多个带有Observables的HTTP请求:一个接一个成功
【发布时间】:2017-08-28 13:22:05
【问题描述】:

我对 Angular 4 和 Observables 以及与它相关的一切都是新手。 我正在尝试一个接一个地执行两个http 请求(仅第一个请求成功时)。

我正在使用此代码:

public getCompany(id: string): any {
    let company = null;

    this.authService.isValidUser().subscribe(response => {
      const token = this.tokenStorageService.getTokenFromStorage();
      const requestUrl = environment.gatewayUrl + environment.companyService + environment.getCompanyEndPoint + id;
      const headers = new Headers();
      headers.set('Authorization', 'Bearer ' + token);
      const options = new RequestOptions({headers: headers});

      return this.http.get(requestUrl, options).catch(this.errorService.handleError);

    }, (error: AppError) => {
       // ........ //
    });
  }

这是isValidUser()方法代码:

  public isValidUser(): any {
    const token = this.tokeStorageService.getTokenFromStorage();
    if (!token) {
      console.log('cannot find token');
      return false;
    }

    const requestUrl = environment.gatewayUrl + environment.authorizationService + environment.userServiceEndPoint;
    const headers = new Headers();
    headers.set('Authorization', 'Bearer ' + token);
    const options = new RequestOptions({headers: headers});

    return this.http.get(requestUrl, options).catch(this.errorService.handleError);
  }

这里的想法是只在authService.isValidUser() 代码工作后返回return this.http.get(requestUrl, options).catch(this.errorService.handleError);

我认为这不是执行此类请求的正确方法,因为我的第二个请求在第一个请求之前已经完成。

也许我错过了如何正确执行此操作的方法?

谢谢。

【问题讨论】:

  • since my first request is already completed before the second one does -- 这就是你想要做的,不是吗??
  • 呃,我的错。第二个在第一个完成之前完成
  • 在您的代码中,第一个在第二个之前完成...第一个请求的结果是response

标签: angular angular2-observables


【解决方案1】:

您尝试链接这两个函数的代码在哪里?

您可以使用switchMap 运算符实现您想要的。这是docs

我认为你需要这样的东西:

isValidUser()
  .filter(isValidUser => isValidUser) // <-- perhaps you need this filter since you want to make getCompany call only if user is valid
  .switchMap(() => getCompany())
  .subscribe(...do something...);

别忘了添加import 'rxjs/add/operator/switchMap';。您也可以使用mergeMapflatMapmergeMapflatMap 的同义词),但不是首选。

正如@BeetleJuice 在 cmets 中提到的:为什么switchMap 更好?例如,您使用 mergeMap 或 flatMap 并且某些原因导致该代码的另一个调用。即使两个第一个请求没有完成,也会发送新的请求。甚至有可能第二个请求包比第一个请求完成得更快。在第一个捆绑包完成后,您的状态中有错误的数据。为了解决这个问题,RxJS 提供了完美的操作符switchMap。如果您在上述情况下使用此运算符,则将取消第一个 observable(第一个请求包)。只有最后一个可观察的(来自最后一个调用)会保持活动状态。只有当您有可能在短时间内多次运行该代码时,您才需要 switchMap。如果你知道这段代码只会运行一次,mergeMap/flatMap 也会为你做同样的事情。

另外,请查看this post

2020 年 3 月 28 日更新:使用新版本的 rxjs,您不能再在返回的 Observable 上调用 switchMap 运算符。相反,您需要在 observable 上调用 pipe 并传入之后应该发生的事情。例如:

isValidUser()
  .pipe(
    switchMap(() => getCompany())
  )
  .subscribe(...do something...)

多个运算符也可以传递给管道函数。更多信息可以在 rxjs 网站上找到operators page

【讨论】:

  • 酷。那么这就是答案。
  • 沙里科夫,@DenissM。 switchMap 是比mergeMap 更好的选择,因为在这个用例中,您会希望保留执行顺序——第二个http 请求只能在第一个http 请求解决后发出。 mergeMap 允许发出多个第一种类型的请求,而第二个缓慢的请求通过网络传输。
  • @BeetleJuice 我更新了。我试图用我的解释来解释。你认为一切都正确吗?还是我应该修复?
  • 谢谢。我认为这是正确的,但由 OP 来测试它是否适用于他或她的项目
  • @SharikovVladislav 我明天会测试并让你们知道。非常感谢!我也在考虑 switchMap,因为当我之前读到它时,它对我来说更有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-21
  • 2017-05-08
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多