await嵌套循环问题:如何让外层循环等待内层异步请求按顺序执行
问题原因
- 你当前
processTransactionActions内部用map遍历tx.actions时传入了异步函数,会直接生成并行执行的Promise数组,不会等待内部异步逻辑完成,也不保证执行顺序 async标记的函数如果直接返回Promise数组,外层await只会等待该数组本身(非Promise值立即返回),不会等待数组内所有异步操作完成,因此外层循环会直接进入下一轮迭代
修复方案
第一步:修改processTransactionActions实现
用for...of遍历替换map,保证action逐个按顺序执行,所有操作完成后再返回结果:
async processTransactionActions(tx, blockHeader) { const actionResults = []; // 逐个遍历action,前一个执行完成才会处理下一个 for (const action of tx.actions) { const actionType = Object.keys(action)[0]; if (actionType !== ACTION_TYPE.FUNCTION_CALL) { actionResults.push(void 0); continue; } try { const { method_name, args } = action[actionType]; let currentResult; switch (method_name) { case METHOD_TYPE.INIT: { const initTx = createNearHTLC(args, tx, blockHeader); const claim = await this.htlcService.create(initTx); if (claim) console.log('found init'); currentResult = claim; break; } case METHOD_TYPE.CLAIM: { const claimTx = createClaim(args, tx, blockHeader); currentResult = await this.htlcService.findAndSetClaimTx( { secretHash: claimTx.secretHash, 'raw.contractAddress': claimTx.contractAddress }, claimTx.claimTx, ); break; } case METHOD_TYPE.REFUND: { const refundTx = createRefund(tx, blockHeader); const refunded = await this.htlcService.findAndSetRefundTx( { 'raw.contractAddress': refundTx.contractAddress }, refundTx.refundTx, ); if (refunded) console.log('found refunded'); console.log('no refund'); currentResult = refunded; break; } default: currentResult = void 0; } actionResults.push(currentResult); } catch (error) { if (error.code !== 11000) throw error; actionResults.push(void 0); } } return actionResults; }
第二步:外层循环无需修改
你原本的外层for...of循环已经搭配了await调用processTransactionActions,修改后的processTransactionActions是标准async函数,会返回一个等待所有action处理完成的Promise,外层循环会自动等待当前block的所有transaction、transaction的所有action全部按顺序处理完成后,才会进入下一个block的迭代。
补充说明
如果你不需要action严格按顺序执行,只需要等待所有action执行完成后再处理下一个transaction,可以不用替换for...of,只需要在原map逻辑后加await Promise.all(...)即可:
async processTransactionActions(tx, blockHeader) { const actionPromises = tx.actions.map(async (action) => { // 保留你原有的map内部逻辑不变 }); // 等待所有action异步操作完成 return await Promise.all(actionPromises); }
这种写法下同一个transaction的多个action会并行处理,效率更高,但不保证action的执行顺序,可根据你的需求选择。
内容的提问来源于stack exchange,提问作者Andon Mitev
相关产品推荐
相关产品推荐

