JS多层异步回调全部完成后仅单次调用指定函数的实现方案
需求说明
遍历长度不固定的对象数组travelDataGroups[{}],在forEach()循环中调用异步方法newUser(),该方法内部还需调用另一个异步方法loadOtherUsersPayRate()。需要在所有回调执行完成、循环结束后调用makeWorkbookDownloadObj(),但该方法仅能调用一次,否则会损坏生成的对象。
原问题代码
myGroupWorkReportObj.travelDataGroups.forEach( travelerData => { // 为当前用户添加薪资标准 const someUser = new User( travelerData.employeeId , function() { // 为当前用户和项目添加薪资标准 const projectId = travelerData.projectId; const payRate = loadOtherUsersPayRate( projectId, someUser ) .then( payRate => { // 创建差旅数据行 const rowOfData = [ travelerData.firstName, travelerData.lastName, travelerData.travelHours, financial( payRate.pay / 2 ) ]; // 将数据行推入表格 thisSheet.data.push( rowOfData ); // 需要在所有回调完成后仅调用一次 // makeWorkbookDownloadObj( workbookObj ); }); });
最终可运行代码
核心实现逻辑是将每个异步流程包装为Promise,存入数组后通过Promise.allSettled等待所有异步执行完成,再统一调用目标方法:
const userPromises = []; // 将User类的实例化回调包装为Promise var aUserPromise = ( travelerData ) => { return new Promise( ( resolve, reject ) => { new User( travelerData.employeeId, ( someUserObj ) => { // 加载对应用户和项目的薪资标准 loadOtherUsersPayRate( travelerData.projectId, someUserObj ) .then( payRate => { // 创建差旅数据行 const rowOfData = [ travelerData.firstName, travelerData.lastName, travelerData.travelHours, financial( payRate.pay / 2 ) ]; // 将数据行推入表格 thisSheet.data.push( rowOfData ); resolve(); } ); } ); } ); }; myGroupWorkReportObj.travelDataGroups.forEach(( travelerData ) => { // 执行异步函数,将Promise实例存入数组 var myRun = aUserPromise( travelerData ); userPromises.push( myRun ); }); // 等待所有异步执行完成后,仅调用一次下载对象生成方法 Promise.allSettled( userPromises ) .then( ()=> { makeWorkbookDownloadObj( workbookObj ) });
内容的提问来源于stack exchange,提问作者Aaron
相关产品推荐
相关产品推荐

