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

JavaScript递归异步函数执行顺序问题及解决方案

异步递归获取树形工作项数据时,await未等待所有递归完成的问题解决

问题场景

我需要从文件服务器获取工作项的完整树形结构数据,用全局变量workItems存储结果。写了两个异步函数:updateChartData负责触发数据更新,buildChartData带递归逻辑用来逐层拉取节点信息,但遇到了问题:明明声明了异步函数并使用了await,程序却会提前结束等待,导致updateChartData打印的workItems不完整。递归次数不确定,没法用固定延迟解决,尝试过返回Promise但首次递归后就直接resolve,setTimeout也不起作用。

原代码实现

updateChartData函数

async function updateChartData(){
    console.log("Updating chart with ID", 1);

    await buildChartData(1).then(
        console.log(workItems)
    )
}

buildChartData函数

async function buildChartData(currentID){  
    axios.get(`http://localhost:8888/_wit/workItems?id=${currentID}`).then(function(res){
        let currentItem = res.data.value[0]
        console.log(currentItem)
        // 查找子项
        let childItemIds = []
        for (let link in currentItem.Links){
            let currentLink = currentItem.Links[link]
            childItemIds.push([currentLink.TargetWorkItemId])
            console.log("Found Child",currentLink.TargetWorkItemId)
        };

        workItems[currentItem.WorkItemId] = {
            'Title':currentItem.Title,
            'WorkItemType':currentItem.WorkItemType,
            'State':currentItem.State,
            'Links': childItemIds
        };

        // 递归拉取子项
        if (currentItem.Links.length >0){
            childItemIds.forEach(buildChartData)
        };
    });
};

问题根源

  1. buildChartData内部用了.then()处理axios请求,但没有返回这个Promise,也没用await等待请求完成,导致函数会直接返回一个空的已resolve状态Promise,外层的await根本等不到请求结束。
  2. 递归时用forEach调用异步函数,forEach不支持异步等待,所有递归请求会同时触发,父函数不会等所有子递归完成就结束。
  3. updateChartData里的.then(console.log(workItems))写法错误,这里会立即执行console.log,而不是等buildChartData完成后再执行。

修复后的代码

通过在异步请求和递归循环中都使用await,确保所有异步操作和递归任务都完成后,再继续执行后续逻辑。

修改后的buildChartData函数

async function buildChartData(currentID){   
    const res = await axios.get(`http://localhost:8888/_wit/workItems?id=${currentID}`)
    let currentItem = res.data.value[0]
    console.log(currentItem)
    // 查找子项
    let childItemIds = []
    for (let link in currentItem.Links){
        let currentLink = currentItem.Links[link]
        childItemIds.push([currentLink.TargetWorkItemId])
        console.log("Found Child",currentLink.TargetWorkItemId)
    };

    workItems[currentItem.WorkItemId] = {
        'Title':currentItem.Title,
        'WorkItemType':currentItem.WorkItemType,
        'State':currentItem.State,
        'Links': childItemIds
    };

    // 递归拉取子项,用for await确保逐个等待完成
    if (currentItem.Links.length >0){
        for await (const childId of childItemIds){
            await buildChartData(childId)
        };
    };
}

修改后的updateChartData函数

async function updateChartData(){
    console.log("Updating chart with ID", state.trackedID);

    await buildChartData(state.trackedID)
    console.log(workItems)
}

修复说明

  • 用await axios.get()替代.then(),确保函数等待请求完成后再执行后续逻辑,同时函数会自动返回请求对应的Promise,让外层await能正确等待。
  • 把递归调用的forEach改成for await...of循环,逐个等待每个子项的递归任务完成,保证整个树形结构的数据都拉取完毕。
  • 去掉updateChartData中错误的.then()写法,直接在await之后打印workItems,确保此时数据已经完整。

内容的提问来源于stack exchange,提问作者MLancaster

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:23:17