Angular forEach循环内调用Firebase异步接口返回值为0如何解决
问题原因
你对问题的推测完全正确,Firestore的get()方法返回RxJS Observable对象,subscribe触发后回调逻辑是异步执行的,主线程不会等待回调完成就直接执行了return cost语句,此时所有异步请求还未返回结果,cost始终为初始值0。
解决方法
我们需要将所有异步请求包装后等待全部执行完成再返回结果,这里借助Promise.all实现,同时方法需要改为异步返回Promise<number>类型(异步结果无法直接同步返回,必须用异步容器包装):
代码实现(推荐RxJS 7+版本)
首先导入RxJS提供的firstValueFrom方法将Observable转为Promise:
import { firstValueFrom } from 'rxjs'; async getTotalBookListCost(bookList:string[]):Promise<number> { // 把每本书的查询请求转为Promise,存入数组 const requestPromises = bookList.map(el => firstValueFrom(this.store.doc("Books/"+el).get()) .then(data => { const temp = <Book>data.data(); return temp.cost; }) .catch(error => { this.toastr.error(error.message); return 0; // 单本书查询失败时不计入费用,可按需调整逻辑 }) ); // 等待所有查询请求执行完成 const costList = await Promise.all(requestPromises); // 累加所有书籍费用返回 return costList.reduce((total, current) => total + current, 0); }
如果你使用的是RxJS 6及更早版本,可以替换firstValueFrom为toPromise()方法:
// 旧版本兼容写法 const requestPromises = bookList.map(el => this.store.doc("Books/"+el).get().toPromise() // 后续then、catch逻辑和上面一致 )
调用注意事项
修改后的方法返回Promise类型,调用时需要用await或者.then()获取最终计算结果:
// 方式1:在异步方法中用await调用 const totalCost = await this.getTotalBookListCost(['bookId1', 'bookId2']); console.log('总费用:', totalCost); // 方式2:用.then回调获取结果 this.getTotalBookListCost(['bookId1', 'bookId2']).then(totalCost => { console.log('总费用:', totalCost); });
内容的提问来源于stack exchange,提问作者Ashique Razak
相关产品推荐
相关产品推荐

