Позвоните в Promise внутри Observable - PullRequest
0 голосов
/ 16 февраля 2019

Я должен сделать вызов API (возвращает Promise) после другого вызова API (возвращает Observable).

userService.getAuthUser() возвращает Observable.

userService.updateUser() возвращает Promise.

Я могу добиться этого, поместив updateUser() внутрь getAuthUser()

this.userService.getAuthUser().subscribe((res) =>{
  this.userService.updateUser(res.id, <User>({
    name: 'Sample Name'
  })).then((res) =>{
    console.log('update user success');
  }).catch((err) => {
    console.log('update user failed');
  })
},
(err) => {
  console.log('get auth user failed');
})

Но я чувствую, что это не очень хорошо делать таким образом, черт возьми, обратный вызов, есть ли лучший способ сделать это?

Примечание: я не могу изменить userService.updateUser() на Observable.

Ответы [ 2 ]

0 голосов
/ 16 февраля 2019
import { flatMap, map, catchError } from 'rxjs/operators';
import { of, from } from 'rxjs';

this.userService
  .getAuthUser()
  .pipe(
    flatMap(
      ({ id }) =>
        from(this.userService.updateUser(id)).pipe(
          map(response => {
            console.log('update user success');
            return response;
          }),
          catchError(error => {
            console.log('update user failed');
            return of(error);
          })
        ),
      catchError(error => {
        console.log('get auth user failed');
        return of(error);
      })
    )
  )
  .subscribe();
0 голосов
/ 16 февраля 2019

Есть несколько способов достичь этого.

Один из способов , если вы хотите, чтобы поток getAuthUser оставался активным, - преобразовать обещание в наблюдаемое с помощью изоператор .Это позволит вам продолжить поток и реагировать на ошибки / обрабатывать успех для всего потока.Вы также можете указать, где в потоке реагировать на конкретные ошибки, с помощью оператора catchError .

Что-то похожее на:

this.userService.getAuthUser()
  .pipe(
    catchError(err => {
      // throw an error how you like, see the 'throw' operator
      // can also create with other operators like 'of'
    }),
    switchMap(auth =>
      from( // will detect promise and return observable
        this.userService.updateUser(res.id, <User>({
          name: 'Sample Name'
        }))
      )
    ),
    catchError(err => {
      // throw an error how you like, see the 'throw' operator
      // can also create with other operators like 'of'
    })

  ).subscribe(
    (res) => {
      // if you were expecting data at this point
    }, (err) => {
      // if you threw the error
    }
  )

Другой способ если вам не требуется, чтобы поток оставался активным, вы можете преобразовать Observable из первого потока в Promise с помощью .toPromise().Отсюда у вас есть два типичных пути для подражания.Вы можете использовать async / await или просто связать обещания.

Для асинхронного ожидания, что-то похожее на:

// the method will have to be async for await to not show errors

const authUser = await this.userService.getAuthUser().toPromise();

// determine if you should update
// if so

const updateUserResult = await this.userService.updateUser(res.id, <User>({name: 'Sample Name'}));
...