Typescript中如何等待for循环执行完成后再获取返回结果
问题根因
你代码中getShippingFees返回RxJS Observable对象,subscribe回调属于异步执行逻辑,for循环仅会同步完成所有请求的发起操作,不会等待异步回调执行就会直接返回mainItem.id,因此你拿到的永远是未更新的初始值。
绝对不建议通过设置固定等待时间解决该问题,网络请求耗时受网络环境、服务端响应速度等多重因素影响,不存在通用的安全等待时长,哪怕你设置几秒的等待时间,依然有概率出现请求还没返回就提前执行后续逻辑的问题。
可行解决方案
方案1:Observable转Promise+async/await批量等待(推荐)
首先修正你原代码的数组越界bug:for (let i = 0; i <= this.itemIds.length; i ++)需改为i < this.itemIds.length,数组下标从0开始,最大有效值为length-1。
修改后的代码如下:
import { firstValueFrom } from 'rxjs'; // RxJS 7及以上版本推荐使用firstValueFrom替代废弃的toPromise方法 private async findMainItemId() { let mainItem = {id: this.itemIds[0].id, price: 0}; // 批量生成所有请求的Promise const requestTasks = this.itemIds.map(async itemId => { const resp = await firstValueFrom(this.checkoutService.getShippingFees(itemId)); const itemDeliveryTypes = resp.filter(s => s.applied === true); const standardPrice = itemDeliveryTypes.find(dt => dt.name === 'standard').price; if (standardPrice > mainItem.price) { mainItem.id = itemId.id; mainItem.price = standardPrice; } }) // 等待所有请求的回调逻辑全部执行完成 await Promise.all(requestTasks); return mainItem.id; }
调用该方法时直接用await findMainItemId()即可拿到最终计算后的ID。
方案2:RxJS流风格实现(适用于调用方需要订阅结果的场景)
如果你不想用Promise,也可以用RxJS的forkJoin算子组合所有请求流,统一处理后返回结果:
import { forkJoin, map } from 'rxjs'; private findMainItemId() { let mainItem = {id: this.itemIds[0].id, price: 0}; // 组合所有请求为单个流 return forkJoin( this.itemIds.map(itemId => this.checkoutService.getShippingFees(itemId)) ).pipe( map(allResponses => { allResponses.forEach((resp, index) => { const itemId = this.itemIds[index]; const itemDeliveryTypes = resp.filter(s => s.applied === true); const standardPrice = itemDeliveryTypes.find(dt => dt.name === 'standard').price; if (standardPrice > mainItem.price) { mainItem.id = itemId.id; mainItem.price = standardPrice; } }) return mainItem.id; }) ) }
调用该方法时订阅返回的Observable即可:findMainItemId().subscribe(mainId => { // 后续逻辑 })
内容的提问来源于stack exchange,提问作者canbrian
相关产品推荐
相关产品推荐

