我如何在rxjs订阅函数中使用await,并在继续处理事件之前使promise得以解决?
这是一个codepen:https://codepen.io/parliament718/pen/YzKqMJB
let state = { end: 10 };
interval(500).pipe(
switchMap(async (data) => {
console.log('new quote', data);
if(data >= state.end) {
state.end = await getData();
console.log('get new end', state);
}
})
)
.subscribe()
async function getData() {
return await new Promise(resolve => {
setTimeout(() => { resolve(state.end + 10) }, 600);
});
}
输出为:
new quote 10
new quote 11
new end {end: 20}
new quote 12
new end {end: 30}
new quote 13
我需要的输出是:
new quote 10
new end {end: 20}
new quote 11
new quote 12
new quote 13
问题是在getData承诺解决之前会触发“ quote 11”,从而导致两次调用getData。
我认为switchMap应该可以处理这种情况。
答案 0 :(得分:1)
部分问题是您试图在可观察的上下文中使用Promise。当外部可观察对象发出时,switchMap
取消订阅任何内部可观察对象,但这仍然不是您想要的行为。您需要遵循以下原则:
interval(500).pipe(
concatMap(data => { // concatMap places new emissions in a queue, waiting until each inner Observable completes before emitting the next one
console.log('new quote', data);
if(data >= state.end) {
return from(getData()); // creates an Observable which completes when the Promise resolves
} else {
return of(false); // allows us to filter out states where getData isn't called
}
}),
filter(newEnd => !!newEnd), // ignore anything where getData isn't called
tap(newEnd => { // only if getData was called
state.end = newEnd;
console.log('get new end', state);
})
).subscribe();
使用concatMap
缓存下一个值,因此每个步骤中的比较仅在上一个完成后的 之后进行。