Angular中for循环早于Observable执行 无法获取API返回消息如何解决
你遇到的问题本质是httpSend返回的Observable是异步对象,subscribe回调属于非阻塞逻辑,for循环不会等待接口返回就会执行完毕,因此你既没法收集所有返回消息,也无法判断所有请求什么时候全部完成。
解决方案
你可以将Observable转成Promise,配合async/await实现等待所有请求完成,同时收集所有返回消息,分两种适用场景:
方案1:并行请求(推荐,效率更高)
所有请求同时发出,等待全部返回后再执行后续逻辑,适合不需要严格按顺序提交的场景。
首先需要从rxjs导入转换方法:
import { firstValueFrom } from 'rxjs';
修改后的syncOnRoute代码:
async syncOnRoute() { try { // 第一步:从本地数据库读取待同步数据 const res = await this.auth.database.executeSql('select * from onroute where HaveData=?', ['yes']); const requestPool = []; const allMessages = []; // 存储所有接口返回消息 // 第二步:生成所有请求的Promise数组 for (let i = 0; i < res.rows.length; i++) { const row = res.rows.item(i); const params = new HttpParams() .set('CLAIMGUID', row['CLAIMGUID']) .set('JOBGUID', row['JOBGUID']) .set('Latitude', row['Latitude']) .set('Longitude', row['Longitude']) .set('OnRouteDT', row['OnRouteDT']) .set('Desc', this.auth.getdateformatV2()) .set('title', 'onroute'); // 将Observable转为Promise,存入请求池 const req = firstValueFrom(this.auth.httpSend('Service_SaveOnRoute', params, 'post')) .then(msg => { console.log('##SUCCESS ONROUTE SYNC' + JSON.stringify(msg)); allMessages.push({ status: 'success', data: msg }); }) .catch(err => { console.log('##ERROR ONROUTE SYNC' + JSON.stringify(err)); allMessages.push({ status: 'fail', data: err }); // 如果需要某一个请求失败就中断所有,打开下面注释即可 // throw err }); requestPool.push(req); } // 第三步:等待所有请求执行完毕 await Promise.all(requestPool); // 到这里所有请求都已返回,可直接使用allMessages里的所有消息 console.log('全部同步完成,所有返回消息:', allMessages); return allMessages; } catch (e) { console.error('同步流程出现异常:', e); throw e; } }
方案2:串行请求
按数据读取顺序逐个发送请求,上一个请求返回后再发下一个,适合需要严格按顺序提交的场景,代码如下:
async syncOnRoute() { try { const res = await this.auth.database.executeSql('select * from onroute where HaveData=?', ['yes']); const allMessages = []; // 循环内逐个等待请求返回 for (let i = 0; i < res.rows.length; i++) { const row = res.rows.item(i); const params = new HttpParams() .set('CLAIMGUID', row['CLAIMGUID']) .set('JOBGUID', row['JOBGUID']) .set('Latitude', row['Latitude']) .set('Longitude', row['Longitude']) .set('OnRouteDT', row['OnRouteDT']) .set('Desc', this.auth.getdateformatV2()) .set('title', 'onroute'); try { const msg = await firstValueFrom(this.auth.httpSend('Service_SaveOnRoute', params, 'post')); console.log('##SUCCESS ONROUTE SYNC' + JSON.stringify(msg)); allMessages.push({ status: 'success', data: msg }); } catch (err) { console.log('##ERROR ONROUTE SYNC' + JSON.stringify(err)); allMessages.push({ status: 'fail', data: err }); // 如果需要某一个请求失败就中断后续请求,打开下面注释即可 // throw err } } console.log('全部同步完成,所有返回消息:', allMessages); return allMessages; } catch (e) { console.error('同步流程出现异常:', e); throw e; } }
补充说明
- 两种方案修改后
syncOnRoute仍然返回Promise,不影响你原有调用逻辑 - 若你使用的rxjs版本低于7,没有
firstValueFrom方法,可以直接用.toPromise()替代,效果一致 - 原代码中错误回调的打印误写了SUCCESS标识,上面的代码已经修正
内容的提问来源于stack exchange,提问作者Md Danish
相关产品推荐
相关产品推荐

