Angular ngrx中如何让Promise.all等待前置Promise执行完成?
问题根因
这不是Promise.all的机制问题,是你写的异步时序错了:
- 代码执行同步流时,
this.getNameData().then(...)里的push逻辑会被挂到微任务队列,不会立刻执行 - 同步流会继续往下跑,遍历names把其他Promise塞进数组后,立刻执行
Promise.all(promisses),这时候那个耗时请求对应的Promise根本还没被push进数组,Promise.all自然不会等它 - 另外你代码里还有几处拼写错误:
Promisse正确拼写是Promise,fromPromisse是RxJS旧版的fromPromise(新版RxJS直接用from即可),getDataSucess正确拼写是getDataSuccess,这些也会导致运行异常。
修复方案
方案1:保持Promise写法,调整时序
所有依赖前置异步结果的逻辑,必须放到前置Promise的then回调里,等前置任务resolve之后再组装完整的Promise数组,再调用Promise.all:
effect = this.actions$.ofType(projectAction.GETDATA) .switchMap(([action, state]) => { return Observable.fromPromise( // 先等长任务完成拿到结果 this.getNameData().then(serverData => { const promises: Promise<any>[] = []; // 把依赖长任务结果的请求放进数组 promises.push(this.dataService.getAllNameData(serverData)); // 再放入其他普通请求 names.forEach((name) => { promises.push(this.dataService.getAllNameData(name)); }); // 此时数组是完整的,再调用Promise.all等待所有任务 return Promise.all(promises); }).then((results) => { // 处理全量结果逻辑 return new dataAction.getDataSuccess(results); }) ); });
方案2:RxJS原生写法(更符合NgRx最佳实践)
NgRx Effect本身基于RxJS实现,不建议混用Promise和Observable,容易出时序问题。用RxJS原生操作符实现的话逻辑更清晰,forkJoin就是Observable版的Promise.all,会等待所有传入的流完成后返回结果数组:
import { from, of } from 'rxjs'; import { switchMap, map, catchError } from 'rxjs/operators'; effect = this.actions$.ofType(projectAction.GETDATA) .pipe( switchMap(([action, state]) => { // 先执行前置长任务,转Promise为Observable return from(this.getNameData()).pipe( switchMap(serverData => { // 组装全部请求流 const requestStreams$ = [ this.dataService.getAllNameData(serverData), ...names.map(name => this.dataService.getAllNameData(name)) ]; // 等待所有请求完成 return forkJoin(requestStreams$); }), map(results => new dataAction.getDataSuccess(results)), // 记得补充错误处理,否则请求报错后effect会终止,无法响应后续动作 catchError(error => of(new dataAction.getDataFail(error))) ); }) );
额外提醒:如果你的
dataService本身是Angular封装的HttpClient服务,它的方法默认返回Observable,不需要转成Promise用,直接把返回值放进forkJoin的数组里即可,少一层转换性能更好,也更不容易出错。
内容的提问来源于stack exchange,提问作者TheKing
相关产品推荐
相关产品推荐

