RxJS exhaustMap未按预期运行,第二个投影Observable被忽略问题
问题原因分析
exhaustMap的核心工作逻辑是:只要当前存在尚未完成的投影Observable,所有在这期间由源Observable发射的新值都会被直接丢弃,不会生成对应的投影Observable,直到当前的投影Observable完全结束后,才会响应后续源发射的新值。
你的代码中,源Observable是from(['a','b']),它是同步发射值的,会在代码执行到pipe的瞬间立刻连续发射'a'和'b'两个值:
- 第一个值
'a'发射时,exhaustMap还没有正在处理的投影Observable,所以正常生成对应的getData('a')投影Observable并开始执行 - 紧接着源立刻发射了第二个值
'b',此时exhaustMap正在处理'a'对应的投影Observable,所以'b'这个值会被直接丢弃,根本不会生成对应的getData('b')投影Observable,和你给getData('b')设置的7秒延迟没有任何关系。
预期效果实现方案
如果你需要按顺序执行所有源值对应的投影Observable,上一个投影Observable完成后再执行下一个,应该使用concatMap操作符替代exhaustMap,修改后的代码如下:
import { from } from 'rxjs'; import { interval } from 'rxjs'; import { take } from 'rxjs/operators'; import { map, concatMap, delay } from 'rxjs/operators'; const getData = (param) => { if (param == 'a') { return interval(1000).pipe( map(val => param + '-' + val.toString()), take(4), delay(1000) ) } else if (param == 'b') { return interval(1000).pipe( map(val => param + '-' + val.toString()), take(4), delay(7000) ) } } // 使用concatMap按顺序执行所有投影Observable from(['a','b']).pipe( concatMap(param => getData(param)) ).subscribe(val => console.log(val));
修改后代码会先输出a-0到a-3,等待7秒后继续输出b-0到b-3,符合你预期的执行效果。
补充说明
exhaustMap适用的场景是需要忽略前一次请求未完成时触发的重复请求,比如用户频繁点击提交按钮时,只响应第一次点击,直到第一次请求完成前的所有点击都直接忽略,和你当前需要按顺序处理所有请求的场景不匹配。
内容的提问来源于stack exchange,提问作者mkedwards
相关产品推荐
相关产品推荐

