angular - 如何以非可怕的方式使用 rxjs 从各种请求中收集数据?
问题描述
我的用例很简单,我认为它无处不在,但我找不到一个可以体面地解释它的教程。
我想在我的角度模块的 onInit() 中获取各种数据,一些是顺序的,一些是并发的。完成所有这些后,我需要对收集的数据执行同步操作。我希望我的代码具有一半可读性。
假设我有以下内容(所有 observables 返回一次,没有实际的流):
- 1) 一个可观察的路由参数,用于从中获取 Id
- 2) 使用该 ID 获取我的主要实体的请求(顺序)
- 3) 使用从第二点检索到的 id 对不同端点的三个请求以获取额外数据(与第 2 点连续,但可以彼此并发运行)
我只是想获取所有这些数据,将其打包到一个可观察对象中,然后订阅它,这样我就可以在该订阅回调中运行我的实际操作。
我在找什么:一个简单的伪代码/代码结构,它告诉我哪些运算符放在哪个序列中。“为什么”的奖励积分。
$Obs1.pipe(mergemap(...))
如果 Rxjs 与干净的代码完全兼容,那么可读性的额外奖励。是的,我对我无法理解这一点感到沮丧,而且完全缺乏这方面的例子。
解决方案
requestRest(data1) {
// parallel request logic encapsulated in a function
return forkJoin(
this.req2(data1),
this.req3(data1),
this.req4(data1)
);
}
ngOnInit() {
// store id observable in a reusable variable (just to illustrate concept)
const id$ = this.route.params.pipe(
map(p => p['id'])
);
id$.pipe(
// switch off id into req1
switchMap(id => this.req1(id)),
// switch off req1 into rest of data
switchMap(data1 => this.requestRest(data1).pipe(
// inner map to combine data1 with rest of data
map(restOfData => [data1, ...restOfData])))
).subscribe(
([d1, d2, d3, d4]) => console.log("got all the data")
)
}
rxjs 是一个强大的库,用于构建处理数据流的管道。您可以构建和组合不同的管道,但您认为合适。有一点学习曲线,但是一旦你克服了它,你就可以处理你能想到的任何数据流。每个前端事件(http 请求、websocekts、表单输入、超时、间隔、点击、鼠标移动等)都是一个数据流,这使得 rxjs 成为一个非常有价值的学习工具。
就 rxjs 流而言,这是一个微不足道的例子,因为顺序和并行执行和转换是基础。当您考虑诸如错误处理、重试逻辑、缓存等大多数生产应用程序都需要的东西时,它会变得更加强大。
switchMap
单独是 rxjs 提供的最强大的工具之一,因为它处理取消逻辑,如果 id 参数在您的请求进行时发生更改,保证您从正确的 id 获得结果,并且不会因请求之间的竞争条件而冒错误的风险.
推荐阅读
- typescript - 理解 TypeScript 中的泛型约束扩展
- django - 为什么 django 对所有与模型相关的功能都使用“ModelName.objects”
- asp.net-core - Auth0 api 返回 401 www-authenticate: Bearer error="invalid_token" in .net core web api
- javascript - Vanilla JavaScript - 如何检查在多个选择选项中选择了一个选项?
- laravel - 更新 User.vue 文件后浏览器未显示更改
- python - 我如何等待任何结束而不是特定线程的线程?
- python - django 2.2 上不存在 ContentType 匹配查询
- typescript - useStaticQuery:无效的挂钩调用。Hooks 只能在函数组件的主体内部调用
- lua - 我可以使用 os.date 将秒转换为时间格式吗?
- python - 使用 Kivy 安装并运行额外的 APK 文件