带setTimeout的JavaScript递归函数实现及代码完善求助
完善结合setTimeout的JavaScript递归遍历函数
我来帮你搞定这个带异步延迟的递归遍历需求,先把原始代码里的问题修正,再实现符合预期的逻辑:
首先,原始数据存在语法错误(末尾缺少闭合的]),先补全并整理格式:
// 修正后的树形结构数据 var data = [ { id: "0" }, { id: "1", children: [ { id: "1.1", children: [ { id: "1.1.1", children: [ { id: "1.1.1.1", children: [ { id: "1.1.1.1.1" }, { id: "1.1.1.1.2" }, { id: "1.1.1.1.3" } ] }, { id: "1.1.1.2" }, { id: "1.1.1.3" } ] }, { id: "1.1.2" }, { id: "1.1.3" } ] }, { id: "1.2" }, { id: "1.3" } ] }, { id: "2" }, { id: "3" } ];
接下来是完善后的结合setTimeout的异步递归遍历函数,实现深度优先遍历,并且每一步都异步执行,避免阻塞主线程:
function recursiveTraverse(nodes) { // 递归终止条件:节点数组为空时直接返回 if (!nodes || nodes.length === 0) return; // 复制数组,避免修改原始数据(原代码的shift会直接修改原数组,这里优化) const remainingNodes = [...nodes]; const currentNode = remainingNodes.shift(); // 用setTimeout包裹异步逻辑,这里设置100ms延迟,可按需调整 setTimeout(() => { // 输出当前节点ID console.log(currentNode.id); // 优先递归处理当前节点的子节点(如果存在) if (currentNode.children) { recursiveTraverse(currentNode.children); } // 处理完当前节点及其子节点后,再递归处理剩余的兄弟节点 recursiveTraverse(remainingNodes); }, 100); } // 启动遍历 recursiveTraverse(data);
关键逻辑说明
- 避免修改原数据:使用扩展运算符
[...nodes]复制数组,再执行shift(),这样原始的data数组不会被修改,保证数据的完整性。 - 异步执行:每个节点的处理都放在
setTimeout中,让JavaScript事件循环可以穿插处理其他任务,不会造成主线程阻塞;同时也能实现按顺序延迟输出节点ID的效果。 - 深度优先遍历顺序:先输出当前节点,再遍历其所有子节点,最后处理剩余的兄弟节点,输出顺序会是:
0 →1 →1.1 →1.1.1 →1.1.1.1 →1.1.1.1.1 →1.1.1.1.2 →1.1.1.1.3 →1.1.1.2 →1.1.1.3 →1.1.2 →1.1.3 →1.2 →1.3 →2 →3。 - 防止栈溢出:异步递归把调用放到下一个事件循环,即使树形结构极深,也不会触发同步递归的栈溢出错误。
可选调整
如果需要广度优先遍历(先处理所有兄弟节点,再处理子节点),可以调整递归顺序,把处理剩余兄弟节点的逻辑放在子节点之前:
setTimeout(() => { console.log(currentNode.id); // 先处理剩余兄弟节点 recursiveTraverse(remainingNodes); // 再处理子节点 if (currentNode.children) { recursiveTraverse(currentNode.children); } }, 100);
内容的提问来源于stack exchange,提问作者Manish Pradhan
相关产品推荐
相关产品推荐

