Как я могу убедиться, что все мои наблюдаемые завершены, прежде чем показывать тостовое сообщение? - PullRequest
0 голосов
/ 26 марта 2019

У меня есть сценарий, в котором я должен сделать несколько вызовов API, а затем показать несколько тостовых сообщений, информирующих пользователя, если вызовы были успешными или неудачными. В приведенном ниже коде метод processSaveResponses вызывается до разрешения наблюдаемых. Метод processSaveResponses отвечает за отображение всплывающих сообщений. Я понимаю, что это ожидаемое поведение, поскольку наблюдаемые являются асинхронными, но я не знаю, как «ждать», когда наблюдаемые закончили.

Методы deliveryPreferencesService.save и deliveryPreferencesService.saveAutoEnroll не зависят друг от друга, но deliveryPreferencesService.saveAutoEnroll не следует вызывать в случае сбоя deliveryPreferencesService.save.

  private saveChanges(changeSet: DeliveryPreferencesChangeSet) {

    let deliveryPrefernceResult;
    let saveAutoEnroll = true;

    const { accountPreferences: accountPreferenceChanges, autoEnrollPreferences: autoEnrollPreferenceChanges } = changeSet.changes;

    if (accountPreferenceChanges.length) {
      this.deliveryPreferencesService.save(accountPreferenceChanges).
        subscribe(
          () => deliveryPrefernceResult = true,
          () => saveAutoEnroll = false);
    }

    if (autoEnrollPreferenceChanges.length) {
      if (saveAutoEnroll) {
        this.deliveryPreferencesService.saveAutoEnroll(autoEnrollPreferenceChanges).
          subscribe(
            () => console.log('save auto enroll completed'),
            () => saveAutoEnroll = false);
      }
    }

    this.processSaveResponses([{ success: deliveryPrefernceResult }, {success: saveAutoEnroll}]);
  }

Вот код для processSaveResponses:

    if (every(responses, ['success', false])) {
      this.showErrorToastr(this.ALL_CHANGES_FAILURE_MESSAGE);
    }
    else if (every(responses, ['success', true])) {
      this.originalPreferences = cloneDeep(this.currentPreferences);
      this.onChange.next();
      this.showSuccessToastr(this.ALL_CHANGES_SUCCESS_MESSAGE);
    }
    else {
      if ((responses[0] as any).success) {
        this.originalPreferences.accountPreferenceSets = cloneDeep(this.currentPreferences.accountPreferenceSets);
        this.showSuccessToastr(this.DELIVERY_PREFERENCES_SUCCESS_MESSAGE);
        this.showErrorToastr(this.AUTO_ENROLL_FAILURE_MESSAGE);
      } else {
        this.originalPreferences.autoEnrollPreferences = cloneDeep(this.currentPreferences.autoEnrollPreferences);
        this.showSuccessToastr(this.AUTO_ENROLL_SUCCESS_MESSAGE);
        this.showErrorToastr(this.DELIVERY_PREFERENCES_FAILURE_MESSAGE);
      }
    }
  }

Любая помощь будет оценена. Я использую rxjs версии 5.5.2.

Ответы [ 3 ]

2 голосов
/ 26 марта 2019

Попробуйте использовать switchMap, как описано здесь. Я думаю, это может быть использовано в вашем случае. https://www.learnrxjs.io/operators/transformation/switchmap.html

this.deliveryPreferencesService.save(accountPreferenceChanges)
  .pipe(
    switchMap(x => this.deliveryPreferencesService.saveAutoEnroll(autoEnrollPreferenceChanges))
  )
  .subscribe(() => {
    // TODO something
  })

В этом случае this.deliveryPreferencesService.saveAutoEnroll(autoEnrollPreferenceChanges) будет вызываться только после успешного this.deliveryPreferencesService.save(accountPreferenceChanges)

0 голосов
/ 26 марта 2019

Извините, у меня есть. Вы можете сделать это, используя async \ await с обещаниями. Теперь это должно работать по вашему сценарию.

  private async saveChanges(changeSet: DeliveryPreferencesChangeSet) {
    const { accountPreferences: accountPreferenceChanges, autoEnrollPreferences: autoEnrollPreferenceChanges } = changeSet.changes;

    if (accountPreferenceChanges.length) {
      await this.deliveryPreferencesService.save(accountPreferenceChanges).toPromise();
    }

    if (autoEnrollPreferenceChanges.length) {

        await this.deliveryPreferencesService.saveAutoEnroll(autoEnrollPreferenceChanges).toPromise();
    }

    this.processSaveResponses([{ success: true }, {success: true}]);
  }

Подробнее об асинхронности / ожидании в TS https://tutorialedge.net/typescript/async-await-in-typescript-tutorial/

0 голосов
/ 26 марта 2019

Вам необходимо использовать zip

import { of, zip } from 'rxjs';



const x1$ = of('Hello');
const x2$ = of('World!');
const x3$ = of('Goodbye');
const x4$ = of('World!');

const subscription = zip(x1$, x2$, x3$, x4$).subscribe( res => {
  console.log(res);
});

["Hello", "World!", "Goodbye", "World!"]

ОК ?

...