在 Observable 中调用 Promise

had*_*des 3 rxjs es6-promise angular

我必须Promise在另一个 API 调用(返回Observable)之后进行 API 调用(返回)。

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');
})
Run Code Online (Sandbox Code Playgroud)

但我觉得这样做不太好,有点回调地狱,有什么更好的方法吗?

注意:我无法更改userService.updateUser()Observable.

小智 5

有几种方法可以实现这一点。

如果您希望 getAuthUser 流保持活动状态,一种方法是使用from 运算符将承诺转换为可观察的。这将允许您继续流并响应整个流的错误/处理成功。您还可以使用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
    }
  )
Run Code Online (Sandbox Code Playgroud)

另一种方法,如果您不需要流保持活动状态,您可以将 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'}));
Run Code Online (Sandbox Code Playgroud)