Как выполнить Observable последовательно, что зависит друг от друга - PullRequest
1 голос
/ 31 марта 2020

Мне нужен совет о том, как мне достичь заявленного названия. Мой сценарий такой. У меня есть три метода в моем сервисе isUserEnable(), isLicenseStatusEnable() и resetPassword(), и они должны выполняться последовательно. Во-первых, я должен убедиться, что пользователь включен. Если пользователь включен, я должен убедиться, что статус лицензии также включен. Наконец, теперь я могу выполнить метод сброса в моем сервисе. Если какой-либо из первых 2 методов вернет false, то он должен прервать сброс пароля и не должен продолжать выполнять последующие методы.

Сервис

@Injectable({
    providedIn: 'root'
})
export class PasswordResetService {
    isUserEnable(user: string): Observable<boolean> {
        return true;
    }

    isLicenseStatusEnable(user: string): Observable<boolean> {
        return true
    }

    resetPassword() {
        // reset password code
    }
}

У меня есть код ниже и введите delay(5000) для имитации выполнения. Но это не было выполнено один за другим. Я не уверен, как мне реализовать это, чтобы выполнить по одному.

  /**
   * Check user status
   */
  userPasswordReset() {
    let userEnabled ;

    this.passwordResetService.isUserEnable('example_user')
      .pipe(
        tap(_ => TASKS_DATA[0].status = TaskStatus.Started),
        delay(5000),
        map(x => {
          TASKS_DATA[0].taskdescription = "User is enable";
          TASKS_DATA[0].status = TaskStatus.Success;
        })
      )
      .subscribe(result => {
        userEnabled = result;
      });

    this.passwordResetService.isLicenseStatusEnable('example_user')
      .pipe(
        tap(_ => TASKS_DATA[1].status = TaskStatus.Started),
        delay(5000),
        map(x => {
          TASKS_DATA[1].taskdescription = "License is enable";
          TASKS_DATA[1].status = TaskStatus.Success;
        })
      )
      .subscribe(result => {
        return result;
      });
  }

Любые предложения будут очень благодарны. ТИА!

Ответы [ 3 ]

0 голосов
/ 31 марта 2020

мы можем использовать оператор switchMap из rx js. Вы можете найти дополнительную информацию по ссылке ниже:

https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap

SwitchMap используется для последовательного потока, и у нас есть преимущество, что он имеет только одну подписку.

Ниже приведен пример кода для switchMap: (последовательные вызовы API):

https://stackblitz.com/edit/angular-rxjs-operators-examples?file=src%2Fapp%2Fswitch-map%2Fswitch-map.component.ts

Надеюсь, это поможет.

0 голосов
/ 31 марта 2020

Для вызовов, которые зависят от предыдущего результата, вы должны использовать оператор оператора concatMap из rx js

firstApiCall().pipe(
    concatMap(result1 => secondAPICall())
      concatMap( result2 => thirdAPICall())
       concatMap(result3 => fourthAPICall())

).subscribe(
    success => { /* display success msg */ },
    errorData => { /* display error msg */ }
);
0 голосов
/ 31 марта 2020

вы можете использовать async/await, но вам нужно преобразовать наблюдаемое в обещание в toPromise

  async userPasswordReset() {

    const userEnabled = await this.passwordResetService.isUserEnable('example_user')
      .pipe(
        tap(_ => TASKS_DATA[0].status = TaskStatus.Started),
        delay(5000),
        map(x => {
          TASKS_DATA[0].taskdescription = "User is enable";
          TASKS_DATA[0].status = TaskStatus.Success;
        })
      ).toPromise(); // ? convert to Promise


    const result = this.isUserEnable.isLicenseStatusEnable('example_user')
      .pipe(
        tap(_ => TASKS_DATA[1].status = TaskStatus.Started),
        delay(5000),
        map(x => {
          TASKS_DATA[1].taskdescription = "License is enable";
          TASKS_DATA[1].status = TaskStatus.Success;
        })
      ).toPromise(); // ? convert to Promise

  }

Объявление функции asyn c определяет асинхронный функция - функция, которая является объектом AsyncFunction. Асинхронные функции работают в отдельном порядке, чем остальная часть кода, через событие l oop, возвращая неявное Promise в качестве его результата. Но синтаксис и структура кода с использованием асин c функций похожи на стандартные синхронные функции.

Оператор await используется для ожидания Promise. Он может использоваться только внутри функции asyn c.

Подробнее о 101 async / await

другой способ идентификатора для перемещения второго opbservable в тело первого наблюдаемого тела подписки

this.passwordResetService.isUserEnable('example_user')
  .pipe(
    tap(_ => TASKS_DATA[0].status = TaskStatus.Started),
    delay(5000),
    map(x => {
      TASKS_DATA[0].taskdescription = "User is enable";
      TASKS_DATA[0].status = TaskStatus.Success;
    })
  )
  .subscribe(result => {
    userEnabled = result;

      this.passwordResetService.isLicenseStatusEnable('example_user')
        .pipe(
          tap(_ => TASKS_DATA[1].status = TaskStatus.Started),
          delay(5000),
          map(x => {
            TASKS_DATA[1].taskdescription = "License is enable";
            TASKS_DATA[1].status = TaskStatus.Success;
          })
        )
        .subscribe(result => {
          return result;
        });

  });

async/await более читабельно, и если у вас есть более двух наблюдаемых, у вас будет такая структура, как ад обратного вызова, поэтому я рекомендую async/await

...