Как использовать await в RxJS - PullRequest
       38

Как использовать await в RxJS

3 голосов
/ 03 октября 2019

Я очень новичок в RxJS

Вот моя функция

getData(id): Observable<any> {

    let accessToken = this.getAccessHeader();

    if (!accessToken) {
        // Here I want to wait till following observable completes, and returns value. Till then do not call next line methods i.e. code outside the if block

        this.getTemptoken().subscribe((res) => {
            accessToken = res.result.accessToken,
        });
    }
    const httpOptions = {
        headers: new HttpHeaders({
            'accessToken': accessToken
        })
    };
    return this.http.post(
        url,
        {
            'id': id
        }, httpOptions
    ).pipe(map((res) => {
        return res;
    }));
}

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

Ответы [ 2 ]

3 голосов
/ 03 октября 2019

Чтобы использовать результат первой наблюдаемой в последующей наблюдаемой, вы можете использовать switchMap в трубе, например:

of("Hello").pipe(
            switchMap(result => of(result + ", World")),
            switchMap(result => of(result + "!")),
          )
          .subscribe(console.log);
// output: Hello, World!

learnrxjs switchmap


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

concat(
  of(1).pipe(delay(2000)),
  of(2).pipe(delay(500)),
  of(3).pipe(delay(1000))
)
.subscribe(console.log);

// output: 1 2 3

learnrxjs concat


Дополнительно вы можете использовать toPromise(), но это AntiPattern. Посмотрите на

RxJS Наблюдаемое взаимодействие с Promises и Async-Await

Например:

const source$ = Observable.interval(1000).take(3); // 0, 1, 2
// waits 3 seconds, then logs "2".
// because the observable takes 3 seconds to complete, and 
// the interval emits incremented numbers starting at 0
async function test() {
  console.log(await source$.toPromise());
}

learnrxjs topromise

1 голос
/ 03 октября 2019

Вот как я бы переписал ваш метод, чтобы он работал так, как вы хотите.

getData(id): Observable<any> {
  let accessToken$ = of(this.getAccessHeader())
    .pipe(
      switchMap(accessToken => accessToken ? of(accessToken) : this.getTemptoken()
        .pipe(
          map(res => res.result.accessToken)
        )
      )
    )

  return accessToken$
    .pipe(
      map(accessToken => {
        headers: new HttpHeaders({
          'accessToken': accessToken
        })
      }),
      switchMap(httpOptions => this.http.post(url, { id }, httpOptions)),
    )
}

accessToken $ отвечает за получение accesToken в случае, если this.getAccessHeader () не дает нам того, что мы хотим. Это происходит внутри switchMap, если у нас есть accessToken, который мы возвращаем (accessToken), иначе мы возвращаем this.getTemptoken ().

Затем мы берем accessToken $, превращаем его в httpOptions и через switchMap мы возвращаем желаемоеthis.http.post. Наконец, тот, кто подпишется на этот метод, получит желаемый http ответ.

...