Angular HttpClient: заставляйте дальнейшие вызовы API ждать, пока не завершится первый - PullRequest
1 голос
/ 17 июня 2019

У меня есть приложение, которое использует файл cookie для входа в систему, который отправляется с большинством запросов / вызовов API для проверки пользователя.(Он устанавливается сервером после успешного входа в систему.)

Проблема заключается в том, что мое приложение выполняет одновременно несколько вызовов API при запуске, что приводит к вызовам с недействительными идентификаторами сеансов, которые затем воссоздаются на стороне сервера длякаждый из этих вызовов, таким образом, они заканчиваются различными идентификаторами сеансов => пользователь получает выход из системы.

Мой план состоит в том, чтобы отправить один вызов 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 Ответ

1 голос
/ 18 июня 2019

1 Вам не нужен forkJoin, вам нужен mergeMap или concatMap, forkJoin обычно плох, почему?потому что, если один запрос завершается неудачно, то все остальные не срабатывают.

mergeMap и concatMap, если, например, один из десяти запросов не выполняется, остальные девять продолжают пытаться завершить.

Разница между mergeMap и concatMapэто способ, которым они выполняют запросы, в mergeMap они отправляются на сервер «одним нажатием», я имею в виду, давайте подумаем, что вы хотите получить 10 дат, mergeMap затем сделает запрос для 10 дат, не ожидая предыдущую.чтобы закончить, пока concatMap ожидает, пока предыдущий завершит добавление нового запроса в очередь.

Здесь у вас есть пример «как использовать concatMap, mergeMap и forkJoin»: https://angular -bojdob.stackblitz.io

Вот это от Томаса (англ.): https://blog.angularindepth.com/practical-rxjs-in-the-wild-requests-with-concatmap-vs-mergemap-vs-forkjoin-11e5b2efe293

...