如何用高效递归算法实现多层API数据拉取?
多层API数据拉取:递归实现的数组越界修复与优化方案
问题背景
需要调用6个API端点拉取服务器数据,构建层级化的响应树。初始实现采用大量嵌套for循环与if判断,代码冗余且难以维护。尝试递归重构时,出现endpoints数组越界问题,即使添加了长度校验也无法解决。
冗余的初始实现
async function fetch_children(endpoint, state) { const temp = await call_api(endpoint, state); state["children"] = await temp; state["endpoint"] = endpoint; return state; } async function loop_over(state) { const item = await fetch_children(endpoints[0], state); if (item["children"]) { for (const idx in item["children"]) { item["children"][idx] = await fetch_children( endpoints[1], item["children"][idx] ); if (item["children"][idx]["children"]) { for (const idm in item["children"][idx]["children"]) { item["children"][idx]["children"][idm] = await fetch_children( endpoints[2], item["children"][idx]["children"][idm] ); if (item["children"][idx]["children"][idm]["children"]) { for (const id in item["children"][idx]["children"][idm][ "children" ]) { item["children"][idx]["children"][idm]["children"][id] = await fetch_children( endpoints[3], item["children"][idx]["children"][idm]["children"][id] ); if ( item["children"][idx]["children"][idm]["children"][id][ "children" ] ) { for (const idd in item["children"][idx]["children"][idm][ "children" ][id]["children"]) { item["children"][idx]["children"][idm]["children"][id][ "children" ][idd] = await fetch_children( endpoints[5], item["children"][idx]["children"][idm]["children"][id][ "children" ][idd] ); } } } } } } } } return item; }
存在问题的递归尝试
async function fetch_children(endpoint, state) { const temp = await call_api(endpoint, state); state["children"] = await temp; state["endpoint"] = endpoint; return state; } async function loop_over(endpoint, place) { const item = await fetch_children(endpoint, place); return item; } async function test(endpoints, state) { state = await loop_over(endpoints.pop(), state); if (state["children"].length >= 1 || endpoints.length >= 1) { for (const idx in state["children"]) { state["children"][idx] = await test(endpoints, state["children"][idx]); } } return state; }
问题根源
- 数组修改导致共享状态污染:使用
endpoints.pop()会直接修改原数组,递归过程中所有子分支共享同一个数组实例,很快就会将数组元素取空,后续pop()会返回undefined,导致API调用传入无效端点。 - 条件判断逻辑错误:
state["children"].length >=1 || endpoints.length >=1的逻辑不符合需求,应该是同时存在子节点和下一层端点时才需要递归。
预期响应树结构
{ "name": "", "id": "", "children": [ { "name": "", "id": "", "children": [ { "name": "", "id": "", "children": [ { "name": "", "id": "", "children": [ { "name": "", "id": "" }, { "name": "", "id": "" }, { "name": "", "id": "" }, { "name": "", "id": "" }, { "name": "", "id": "" }, { "name": "", "id": "" } ], "endpoint": "endpoints[3]" } ], "endpoint": "endpoints[2]" } ], "endpoint": "endpoints[1]" }, { .... }, ... ]
修复后的高效递归实现
核心优化点
- 使用层级索引跟踪当前API端点,避免修改原数组
- 用
Promise.all并行处理子节点,提升拉取效率 - 明确递归终止条件:层级超过端点数量或无子节点
async function fetch_children(endpoint, state) { const temp = await call_api(endpoint, state); state.children = temp; state.endpoint = endpoint; return state; } // 递归构建层级树 async function buildTree(endpoints, state, currentLevel = 0) { // 终止条件:当前层级超出端点列表长度,停止递归 if (currentLevel >= endpoints.length) { return state; } const currentEndpoint = endpoints[currentLevel]; // 调用当前层级的API,更新节点数据 const updatedState = await fetch_children(currentEndpoint, state); // 若存在子节点,且还有下一层端点,并行递归处理所有子节点 if (updatedState.children?.length && currentLevel + 1 < endpoints.length) { updatedState.children = await Promise.all( updatedState.children.map(child => buildTree(endpoints, child, currentLevel + 1)) ); } return updatedState; } // 调用示例:假设初始state是根节点数据,endpoints是6个API端点数组 // buildTree(endpoints, initialRootState).then(tree => console.log(tree));
代码说明
- 层级索引
currentLevel:从0开始,每递归一层自增1,对应endpoints数组的下标,不会修改原数组,避免共享状态问题。 - 并行处理子节点:
Promise.all同时发起所有子节点的API请求,相比串行循环大幅提升效率。 - 明确终止条件:当当前层级超过端点数量时,直接返回当前节点,不会继续递归。
内容的提问来源于stack exchange,提问作者eteturkist
相关产品推荐
相关产品推荐

