JavaScript中异步函数为何不等待Promise执行完成?
异步循环未等待导致执行顺序异常的问题分析与解决
问题根源
你在for...of循环中调用match异步函数时,没有使用await等待函数执行完成,导致循环会快速遍历所有searchCriterias,优先执行每个findOrCreate里的同步代码(前两个console.log),而所有异步的TenderAccount.findOne请求会被批量触发,等这些异步操作全部完成后,才会依次打印Doc的结果。
详细解释
异步函数的执行逻辑是:
async函数中,await之前的代码是同步执行的,遇到await时会暂停函数执行,让出JavaScript线程,等待异步操作完成后才继续执行后续代码。- 当你循环调用
match(searchCriteria)却不加await时,每次调用都会立即执行match内的同步流程(调用findOrCreate并打印前两行日志),随后函数在await TenderAccount.findOne处暂停,循环直接进入下一次迭代,不会等待当前match的异步操作完成。 - 最终所有同步日志先批量输出,等所有
findOne异步请求完成后,才会依次输出Doc相关日志。
解决方案
修改循环逻辑,在调用match时添加await,确保每次迭代都等待当前异步函数执行完成后再进入下一次循环:
// 修正后的循环代码 for (const searchCriteria of searchCriterias) { await match(tender, searchCriteria); // 添加await等待异步函数完成 }
修改后控制台输出会符合预期的顺序:
Search Criteria Name: test-sc Tender Name: test-tender Doc: null Search Criteria Name: test2-sc Tender Name: test2-tender Doc: null Search Criteria Name: test3-sc Tender Name: test3-tender Doc: null
补充:并行执行场景(可选)
如果你的业务场景不需要严格按顺序处理每个searchCriteria,只是希望每个findOrCreate内部的日志顺序正确,可以使用Promise.all并行发起所有异步请求:
// 并行执行(日志仍会先批量输出同步部分,再输出异步结果,但每个findOrCreate内部逻辑不受影响) await Promise.all(searchCriterias.map(searchCriteria => match(tender, searchCriteria)));
注:这种方式下同步日志还是会先全部打印,再打印所有异步结果,适合不需要顺序依赖的批量处理场景。
内容的提问来源于stack exchange,提问作者Julián Álvarez
相关产品推荐
相关产品推荐

