javascript - 深度多分支树递归javascript函数未保留父引用
问题描述
我有一个数据集,其结构如下:
...
{
"id": "id"
"name": "name"
"children": ["IdToChild", "IdToChild"]
}
... And so forth
数据最终将构建一个深度多分支树。流程如下:
- 从具有子引用的数据库中获取父对象
- 从引用中获取孩子
- 将子数组附加到父对象
- 继续 - 如果有更多子引用¨
我的目标是拥有一个结构类似于此的完整树:
{
"id": "myId"
"name": "name 1",
"children": '[
{
"id": "myId"
"name": "name 2",
"children": [
{
...
}
]
},
{
"id": "myId"
"name": "name 3",
"children": [
{
...
},
]
},
]
}
我有以下代码:
async function caller(){
//Fetch parent object from database
await assembletree(parentObj)
}
async function assembletree(parentObj){
let childrenArray = []
for(let index = 0; index < parentObj.children.length; index++){
//Async call to database to get child object by id
childrenArray.push(databaseObject)
}
//Remove existing children property that holds just the Ids
delete parentObj.children
//Assign the childrenArray to a new property named "children"
Object.assign(parentObj, parentObj, {"children": childrenArray})
//Initiate recursion to fetch next children
for(let index = 0; index < parentObj.children.length; index++){
await assembletree(parentObj.children[index]) // <--- 2nd child is never called
}
}
当我有一个单一的深层分支时,上面的代码真的没有问题。但是当我在父对象中遇到多个子对象时,代码只对第一个子对象进行递归。
当我调试我的代码时,我可以看到只有第一个子对象正确触发了递归循环,但第二个子对象永远不会被处理。
当然,我不确定我错过了什么,因为一切对我来说似乎都是有效的。我对上述问题的初步猜测是,由于某种原因,引用失去了对第二个子对象的跟踪。
解决方案
您的主要问题是第二个 for 循环:
for(index = 0; index < parentObj.children.length; index++){
你之前忘记了let
关键字index
。结果是您现在正在使用index
与重复调用共享的全局变量。
添加后,let
您的代码似乎工作正常:
async function assembletree(parentObj){
let childrenArray = []
for(let index = 0; index < parentObj.children.length; index++){
//Async call to database to get child object by id
const databaseObject = await fetchDatabaseObject(parentObj.children[index]);
childrenArray.push(databaseObject)
}
//Remove existing children property that holds just the Ids
delete parentObj.children
//Assign the childrenArray to a new property named "children"
Object.assign(parentObj, parentObj, {"children": childrenArray})
//Initiate recursion to fetch next children
// Added the let keyword below!
for(let index = 0; index < parentObj.children.length; index++){
await assembletree(parentObj.children[index]) // <--- 2nd child is now called
}
}
(async function () {
try {
const object = await fetchDatabaseObject(1);
await assembletree(object);
console.log(object);
} catch (e) {
console.error(e.message);
}
})();
// mock data/database
const records = [{
"id": 1,
"name": "a" ,
"children": [2, 3],
}, {
"id": 2,
"name": "b" ,
"children": [4],
}, {
"id": 3,
"name": "c" ,
"children": [5],
}, {
"id": 4,
"name": "d" ,
"children": [],
}, {
"id": 5,
"name": "e" ,
"children": [],
}];
const indexed = new Map(records.map(record => [record.id, record]));
async function fetchDatabaseObject(id) {
await sleep(100);
return deepDupplicate(indexed.get(id));
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function deepDupplicate(object) {
return JSON.parse(JSON.stringify(object));
}
可以进行很多优化,但我会将这些优化排除在答案的重点之外。
推荐阅读
- javascript - Javascript 在同一台机器上给出不同的时区
- sql-server - 查找具有 2 个或更多连续数字字符的值 (SQL)
- javascript - FormData 在前端定义,在后端未定义
- android - 具有静态 WeakReference 的线程是否能够被垃圾收集或强制 MemoryLeak?
- reactjs - 输入清除按钮在 Microsoft Edge 中不起作用
- flutter - 如何对齐行/列的孩子?
- python - 如何将 .txt 转换为 .rdb 格式
- java - 尝试单击弹出按钮时出现 NoSuchElementException
- c# - PHP DOTNET 适用于 localhost 但不适用于 GoDaddy 共享 Linux 主机
- javascript - 以数组 React 挂钩方式更新对象值