Дождитесь завершения нескольких HTTP-запросов, прежде чем запускать функцию в angular

У меня есть несколько сообщений http, которые извлекают данные JSON из базы данных MySQL. Я хочу, чтобы функция прослушивала их все и запускала следующий фрагмент кода, как только все они возвращали, что данные были получены.

Я пробовал несколько вариантов async с ожиданием, но функция, похоже, не ожидает завершения HTTP-сообщения.

У меня есть служба риска Risk.service.ts, чтобы получить, например, RiskTable:

getRiskTable(): Observable<Risk[]> {
    return this.http.get(`${this.baseUrl}/getRiskTable`).pipe(
      map((res) => {
        this.riskTable = res['data'];
        return this.riskTable;
      }),
      catchError(this.handleError));
  }

На моей панели инструментов я называю этот код:

getRiskTable():any {
    return this.riskService.getRiskTable().subscribe(
      (res: []) => {
        this.riskTable = res; // the value is correctly captured here
        return true;
      },
      (err) => {
        this.error = err;
      }
    );
  }

И затем асинхронная функция, которая запускает несколько из этих функций, теоретически предполагается, что она должна дождаться завершения всех функций, а затем зарегистрировать значение. Но почему-то глобальная переменная this.riskTable в этой функции не определена.

async getAllData(){
    let riskTable = await this.getRiskTable();
    let risks = await this.getAllRisks();

    console.info(riskTable); //This returns stuff
    console.info(risks);
    console.info(this.riskTable); //This returns undefined even though it was set in getRiskTable
  }

Пожалуйста, любые указатели - я очень новичок в angular, и сложность этого меня полностью озадачила. 2 дня и 100-кратные вариации, чтобы заставить это работать Я медленно теряю свои бананы!

Вы можете подумать о forkJoin, который выполняется параллельно (если ни один из них не зависит друг от друга), и в обратном вызове вы можете делать с данными все, что вам нужно.

AT82 25.04.2019 20:44

Хорошо, я быстро просмотрел найденный и пример forkJoin. Они запустили его в службе, чтобы получить все HTTP-запросы, а затем вернуть результат. У меня есть несколько вызовов HTTP, которые должны оставаться модульными. Я хотел бы вызывать их один за другим из разных компонентов, и именно по этой причине я хочу, чтобы компонент мог получить доступ к данным из службы и дождаться их завершения (параллельно было бы идеально, но я возьму что угодно в этот момент).

Brenden Engelbrecht 25.04.2019 20:52
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
3
2
10 357
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Поскольку вы используете Angular, вы должны использовать forkJoin RxJS, чтобы объединить наблюдаемые из обоих методов запроса API в одно наблюдаемое значение и вернуть ему значения с помощью подписка.

Не забудьте импортировать forkJoin в свой компонент.

import { forkJoin } from 'rxjs';

..

getAllData(){
  const riskTable = this.riskService.getRiskTable();
  const risks = this.riskService.getAllRisk();

  forkJoin(riskTable, risks).subscribe(response => { 
    console.info(response);
  })
}

Если вы настаиваете на обработке его как промиса, а не как наблюдаемого, вы можете использовать Обещание.все(), который возвращает их как один промис.

Ответ принят как подходящий

Во-первых, ключевые слова async/await используются с обещаниями, а не с Observable. Таким образом, вы можете преобразовать наблюдаемое в обещание, используя toPromise(), или вы можете использовать rxjs ForkJoin. Вам также нужно изменить методы, чтобы возвращать либо наблюдаемое, либо обещание, вы мало что можете сделать с подпиской, которую возвращает subscribe, когда вы ее вызываете, и это то, что вы сейчас передаете из getRiskTable.

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

import { forkJoin } from 'rxjs';
import { shareReplay } from 'rxjs/operators';

getRiskTable() : Observable<Risk[]> {
  const tableObservable = this.riskService.getRiskTable().pipe(shareReplay());
  tableObservable.subscribe((res) => this.riskTable = res, (err) => {this.error = err;});
  return tableObservable;
}

getAllData() {
  let riskTable = this.getRiskTable();
  let risks = this.getAllRisks(); // should also return some observable

  forkJoin(riskTable, risks).subscribe(_ => {
    // all observables have been completed
  });
}

Обратите внимание, что я также добавил shareReplay, который гарантирует, что несколько подписок на один и тот же наблюдаемый объект не приведут к нескольким вызовам конечной точки вашего API. Один результат распределяется между несколькими подписками на наблюдаемое.

Игорь, сейчас 3 часа ночи. Я чертовски счастлива прямо сейчас, что написала тебе вот это кое-что: Я дизайнер Глупый, визуальный и Немного нытик Дела пошли действительно тяжело Слава Богу Игорь пришел И дал код love @_@ !! 10/10 Люблю тебя!

Brenden Engelbrecht 25.04.2019 21:02

@BrendenEngelbrecht - рад, что у вас все заработало, и я надеюсь, что это все еще имеет смысл утром (после того, как вы немного отдохнете) :)

Igor 25.04.2019 21:04

ваша первая функция getRisk возвращает наблюдаемое, а не обещание, вам нужно сделать .toPromise(), чтобы преобразовать наблюдаемое в обещание. ваша вторая функция getRiskTable подписалась на наблюдаемую, которая очень непоследовательна по сравнению с вашей первой, вы должны делать то же самое, что и ваша первая функция, только возвращать обещание, тогда ваше асинхронное ожидание должно работать.

или вы можете использовать forkjoin(obs1,obs2), зависит от ваших интересов, но оставайтесь последовательными.

Другие вопросы по теме