Angular(4):使用 Observables 的多个 HTTP 请求:一个接一个成功

Den*_* M. 6 angular2-observables angular

Observables我对 Angular 4 以及与之相关的一切都很陌生。我试图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) => {
       // ........ //
    });
  }
Run Code Online (Sandbox Code Playgroud)

这是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);
  }
Run Code Online (Sandbox Code Playgroud)

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

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

也许我缺少一些如何正确执行此操作的方法?

谢谢。

Sha*_*lav 4

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

您可以使用switchMap运算符实现您想要的目的。这是它的文档。

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

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...);
Run Code Online (Sandbox Code Playgroud)

不要忘记添加import 'rxjs/add/operator/switchMap';. 您还可以使用mergeMapor flatMapmergeMap是 的同义词flatMap),但不是首选。

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

另外,请查看这篇文章

2020 年 3 月 28 日更新:使用新版本的 rxjs,您无法再对返回的 Observable 调用 switchMap 运算符。相反,您需要在可观察对象上调用管道并传入之后应该发生的事情。例如:

isValidUser()
  .pipe(
    switchMap(() => getCompany())
  )
  .subscribe(...do something...)
Run Code Online (Sandbox Code Playgroud)

也可以将多个运算符传递到管道函数中。更多信息可以在 rxjs 网站的操作员页面上找到

  • 沙里科夫,@DenissM。`switchMap` 是比 `mergeMap` 更好的选择,因为在这种用例中,您希望保留执行顺序 - 第二个 http 请求只能在第一个 http 请求解析后发出。“mergeMap”允许在通过网络发送缓慢的第二个请求时发出多个第一种类型的请求。 (3认同)