我有一个角度分量,可以订阅其路线参数。每当路由参数更改时,它都会从参数中读取id
并调用一个函数以查找该ID的记录。该函数返回一个promise。解决后,该组件将自己设置属性以进行数据绑定。
在某些情况下,响应似乎混乱了,设置了错误的值。看起来是这样的:
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 <----问题
解决这个问题的最优雅的方法是什么?我曾考虑过将诺言转换为可观察的并试图取消它,但这似乎是举手之劳。我试图找出是否有一种序列化订阅的方法,以使第二个“处理”直到第一个完成时才开始。
答案 0 :(得分:2)
您将要使用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();
}
答案 1 :(得分:0)
您可以在每个呼叫中添加一个“请求ID”,然后将其返回给您。然后在回调中,您可以检查请求ID是否高于您处理的最后一个ID。
对于带有单整数响应的小调用来说,这不是理想的选择,但我将自己隐藏在标头中,并使用拦截器/过滤器在每次请求时将标头回传给客户端。