You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 21:27:03