javascript - 如何使用异步操作维护订阅者的顺序
问题描述
我有一个订阅其路由参数的角度组件。每当路由参数发生变化时,它都会从参数中读取id
并调用一个函数来查找该 id 的记录。该函数返回一个承诺。解析后,组件为自己设置一个属性以进行数据绑定。
在某些情况下,响应似乎乱序,并且设置了错误的值。这是它的样子:
ngOnInit() {
this.route.params.subscribe((params) => {
const id = params['id'];
console.log('processing', id);
this.service.getPerson(id).then((person) => {
console.log('processed id', id);
this.person = person; // sometimes this happens out of order
}
}
}
因此,假设我有一个按名称过滤的文本框,当我键入时,导航事件会发生在id
获得该名称的第一个结果的位置。有时我会看到:
处理 1
处理 2
处理 2
已处理 1 <---- 问题
解决这个问题的最优雅的方法是什么?我考虑过将 promise 转换为 observable 并尝试取消它,但这似乎很严厉。我试图弄清楚是否有一种方法可以序列化订阅,以便第二个“处理”在第一个完成之前不会开始。
解决方案
您将要使用其中一个concatMap
或switchMap
. concatMap
将确保在执行下一个请求之前完成前一个请求的处理。switchMap
还将确保顺序,但如果在下一个请求到来时它仍在处理,它将中止对先前请求的处理。
ngOnInit() {
this.route.params.pipe(
map(params => params['id']),
tap(id => console.log('processing', id)),
concatMap(id => fromPromise(this.service.getPerson(id)).pipe(
tap(person => console.log('processed id', id))
)),
tap(person => this.person = person)
)
.subscribe();
}
推荐阅读
- c# - 我如何知道我的列表中的项目是否已更改?
- r - 如何查看由 for 循环生成的特定训练集和测试集?
- sql - BigQuery:使用 DML 原子地替换日期分区
- git - 如何仅合并来自另一个分支的一些文件
- android - react-native-udp Sochets.createSocket 未定义对象
- excel - 整个工作簿的 SUMIF
- java - Javadoc @link 到 Kotlin 类
- r - R闪亮的checkboxGroup在地图上绘制数据
- laravel - Laravel 5.4 Route [login] 未定义
- scala - 什么可以在尾递归功能中炸毁我的笔记本电脑?