在 Observable 中调用 Promise
Posted
技术标签:
【中文标题】在 Observable 中调用 Promise【英文标题】:Call Promise inside Observable 【发布时间】: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
。
【问题讨论】:
您依赖于 observable 为下一个updateUser()
部分返回的值。所以这很好。如果您想拥有更简洁的代码,请创建另一个方法来使用参数更新用户并在 subscribe 中调用它
您可以将 Observable 转换为 Promise 并链接 Promise。 ***.com/questions/36777284/…***.com/a/54710279/495157
您还可以将 Promise 转换为 Observable ***.com/questions/39319279/… ***.com/questions/37771855/…
【参考方案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) => void' is not assignable to parameter of type '(err: any, caught: Observable<void>) => ObservableInput<>'. Type 'void' is not assignable to type 'ObservableInput<>'.
,我必须使用throw
哪个 catchError 部分(或两者)?抱歉,给出“流”示例有点粗略。我很乐意更新您的发现
实际上,我都抛出了catchError(err => 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();
【讨论】:
以上是关于在 Observable 中调用 Promise的主要内容,如果未能解决你的问题,请参考以下文章
Angular - 在另一个组件中使用 observable(在异步数据调用中获取值)
如何在redux-observable中同时进行多个ajax调用?
React redux-observable:以史诗般的方式进行顺序 API 调用
KnockoutJS - 我们可以为 CSS 更新调用 Observable 函数吗
如何在 React 中正确地进行 GET 调用,返回一个 observable(类似于 Angular 中的方法而不使用 Promise)?