Angular HttpClient:进一步 api 调用等待第一个完成

Angular HttpClient: Make further api calls wait for the first one to finish

我有一个使用登录 cookie 的应用程序,它与大多数 api requests/calls 一起发送来验证用户。 (登录成功后由服务器设置。)

问题是,我的应用程序在启动时同时进行了一堆 api 调用,这导致调用具有无效的会话 ID,然后在服务器端为每个调用重新创建这些调用,因此它们最终以不同的会话 ID => 用户已注销。

我的计划是在彼此允许之前发送一个 api 呼叫。但不知何故我无法让它以正确的顺序工作。

我想出了一个承诺,它将在我的包装器构造函数中的第一次调用完成后得到解决,就像这样

private firstCallMade: Promise<any>;

constructor(
    private http: HttpClient,
    private settings: SettingsProvider)
  {    
    this.settings.getAsyncString("apiEndpoint").then(res =>
    {
      this.apiUrl = res;

      this.firstCallMade = new Promise((resolve, reject) =>
      {
        this.http.get(this.apiUrl + this.firstCallEndpoint, { withCredentials: true })
        .subscribe(
          (result) => {
            this.logger.system(this, 'First Call', `First call successful: ${JSON.stringify(result)}`);
            resolve();
          },
          (error) => {
            this.logger.system(this, 'First Call', `First call failed: ${JSON.stringify(error)}`);
            resolve();
          });
      });
    });
  }

在其他包装器方法中我是这样使用的

  get<T>(endpoint: string): Observable<T>
  {
    return new Observable<T>(subscriber =>
    {
      this.firstCallMade.then(_ =>
      {
        this.http.get<T>(this.apiUrl + endpoint)
          .subscribe(
            next => subscriber.next(next),
            error => subscriber.error(error));
      });
    });
  }

但这不起作用。

我的代码有误吗?

编辑澄清 想要的是全部,但第一个调用可以同时进行,在第一个调用完成后(从而为后续调用设置正确的 cookie 数据)。

1 你不需要forkJoin,你需要mergeMap或concatMap,forkJoin通常是坏的,为什么?因为如果一个请求失败,那么其他所有请求都会失败。

mergeMap 和 concatMap 如果十个请求之一失败,其他九个继续尝试完成。

mergeMap 和 concatMap 之间的区别在于它们执行请求的方式,在 mergeMap 中,它们在 "one push" 中发送到服务器,我的意思是,假设您想提取 10 个日期,mergeMap 然后执行10 个日期的请求无需等待前一个日期完成,而 concatMap 等待前一个日期完成以将新请求添加到队列中。

这里有一个 "how to use concatMap, mergeMap and forkJoin" 的例子:https://angular-bojdob.stackblitz.io

来自 Tomas(英文):https://blog.angularindepth.com/practical-rxjs-in-the-wild-requests-with-concatmap-vs-mergemap-vs-forkjoin-11e5b2efe293