在Angular与RxJS中如何按顺序逐个执行方法 forkJoin是唯一方案吗
顺序执行RxJS异步请求的实现方案
你当前的代码已经用高阶映射实现了串行执行的基础逻辑,仅需要1处修改即可满足需求:将最后一个mergeMap替换为concatMap即可。
核心逻辑说明
concatMap的运行机制为:等待前一个上游Observable完全完成后,才会订阅当前映射生成的新Observable,天然满足逐个按顺序执行、前一个任务结束才触发下一个的要求,非常适配你这种需要将前一步请求结果传递给下一步请求的场景。- 你当前代码中使用的
mergeMap(别名flatMap)会在映射生成Observable后立即订阅,若存在多个并行任务会同时触发,这就是你当前出现非顺序执行的原因。
修正后代码
this.userClient.getUser(userName) .pipe( concatMap( user => { this.user = user; return this.userClient.setStatus(this.user.id, 'banned'); } ), concatMap( user => { //set property... return this.userClient.deleteImg(user.img); } ), // 替换mergeMap为concatMap保证执行顺序 concatMap( user => { this.user = user; return this.userClient.setGroup(user.id, 'test'); } ) ) .subscribe( user => { //actions }, error => console.error(error) )
关于forkJoin的疑问
请问forkJoin是唯一的解决办法吗?
首先明确结论:forkJoin完全不适用于你的需求,更谈不上是唯一解决方案。forkJoin的作用是并行执行所有传入的Observable,等全部任务完成后统一返回所有结果,本身是并行执行工具,和你需要的顺序执行逻辑完全相反。
其他可选的顺序实现方案
如果你的场景不需要依赖前一步请求的返回值,可以直接使用concat操作符批量拼接任务:
import { concat } from 'rxjs'; // 所有任务会按传入顺序逐个执行 concat( this.userClient.getUser(userName), this.userClient.setStatus('123', 'banned'), this.userClient.deleteImg('xxx.jpg'), this.userClient.setGroup('123', 'test') ).subscribe( res => { /* 每完成一个任务触发一次 */ }, err => { /* 任意一步出错直接终止整条链路 */ }, () => { /* 全部任务完成后触发 */ } )
内容的提问来源于stack exchange,提问作者Juri
相关产品推荐
相关产品推荐

