【问题标题】:Call Promise inside Observable在 Observable 中调用 Promise
【发布时间】:2019-07-10 10:06:22
【问题描述】:

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

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

【问题讨论】:

标签: angular rxjs es6-promise


【解决方案1】:

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

一种方法如果您希望 getAuthUser 流保持活动状态,则可以使用 from operator 将 promise 转换为 observable。这将允许您继续流并对整个流的错误/处理成功做出反应。您还可以使用catchError operator 指定流中对特定错误做出反应的位置。

类似于:

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
    }
  )

另一种方法如果您不需要流保持活动状态,您可以使用.toPromise() 将 Observable 从第一个流转换为 Promise。从这里开始,您有两条典型的路径可供遵循。你可以使用async/await,或者只是链接promise。

对于异步等待,类似于:

// 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'}));

【讨论】:

  • 对于catchError 部分,它显示了一些错误Argument of type '(err: any) =&gt; void' is not assignable to parameter of type '(err: any, caught: Observable&lt;void&gt;) =&gt; ObservableInput&lt;{}&gt;'. Type 'void' is not assignable to type 'ObservableInput&lt;{}&gt;'.,我必须使用throw
  • 哪个 catchError 部分(或两者)?抱歉,给出“流”示例有点粗略。我很乐意更新您的发现
  • 实际上,我都抛出了catchError(err =&gt; { console.log(err) throw err; } 之类的错误,否则 IDE 正在崩溃
  • 哦,明白了,“返回可观察的静止图像”部分。 throw 是一种选择,但任何可以创建新 observable 的方式都是有效的。一个用例是捕获错误,在那里处理它,并将流更改为新的 observable,以便下游效果在需要时可以做出不同的反应。
【解决方案2】:
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();

【讨论】:

    猜你喜欢
    • 2021-07-06
    • 2021-01-04
    • 1970-01-01
    • 2017-05-04
    • 2017-12-05
    • 2018-11-25
    • 1970-01-01
    • 2017-07-29
    相关资源
    最近更新 更多