Node.js中async await函数未互相等待执行问题求解
问题根因
- 你定义的
iterateFolders虽然标记为async,但内部用forEach遍历执行异步任务,forEach本身不会等待异步回调执行完成,且函数没有返回所有异步任务的Promise集合,外部无法感知其执行进度 - 在
readDirectory中调用iterateFolders时没有加await,即使内部逻辑正确,也不会等待其执行完成就会走后续代码
修复方案
1. 重写iterateFolders函数
替换forEach为支持异步等待的for...of循环(默认串行执行目录处理,避免多个npm run build同时抢占资源),同时收集所有哈希结果方便后续生成JSON文件,函数最终返回Promise供外部等待。
同步修改getBuildTime为返回Promise的版本,方便感知日志写入完成状态:
// 修改后返回Promise的计时日志函数 function getBuildTime(start,end) { let time = (end - start); let buildTime = `${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()} Build time: ${time} ms \n` // 用fs的promise接口返回Promise return fsp.writeFile('build-time.log', buildTime); } // 修改后的iterateFolders async function iterateFolders(folderPath) { const hashList = []; // 收集所有哈希值,后续生成JSON用 // 串行处理每个目录 for (const files of folderPath) { try { const result = await computeMetaHash(files); console.log({"path":files,"hashCode":result}); hashList.push({path: files, hashCode: result}); // 构建碎片 console.log("%s build...", files); execSync(`cd ${files} && npm run build`, { encoding: 'utf-8' }); // 完成计时 const end = new Date().getTime(); await getBuildTime(start, end); } catch (err) { console.log(err); } } return hashList; // 返回所有哈希结果给后续逻辑使用 }
2. 修改readDirectory调用逻辑
调用iterateFolders时加上await,等待所有任务执行完成后再跑后续逻辑,拿到返回的哈希列表即可生成目标JSON文件:
async function readDirectory() { let files = await readdir(p) const folderPath = files.map(function (file) { return path.join(p, file); }).filter(function (file) { return fs.statSync(file).isDirectory(); }) if (fs.existsSync(hashFile)) { console.log("File exists: ", hashFile); } else { console.log(hashFile," does NOT exist, build will start and hash.json will created:"); start = new Date().getTime(); // 加await等待所有目录处理完成,同时拿到哈希列表 const hashList = await iterateFolders(folderPath, files); // 生成哈希JSON文件 await fsp.writeFile(hashFile, JSON.stringify(hashList, null, 2)); console.log("IT WILL BE LAST ONE ") } }
可选优化:并行处理目录
如果设备资源足够,想要并行处理所有目录提升速度,可以把iterateFolders中的for...of替换为Promise.all实现并发处理:
async function iterateFolders(folderPath) { const taskList = folderPath.map(async files => { const result = await computeMetaHash(files); console.log({"path":files,"hashCode":result}); console.log("%s build...", files); execSync(`cd ${files} && npm run build`, { encoding: 'utf-8' }); const end = new Date().getTime(); await getBuildTime(start,end); return {path: files, hashCode: result}; }) return Promise.all(taskList); }
内容的提问来源于stack exchange,提问作者noobinmath
相关产品推荐
相关产品推荐

