Angular中subscribe后如何正确推送返回数据到数组构建树形结构
目标树形结构
我需要生成如下格式的嵌套树形数据:
[{ number: 3, children: [{ number: 6, children: [{ number: 8, children: [] }] }, { number: 7, children: [{ number: 9, children: [{ number: 8, children: [] }] }] }, { number: 8, children: [] }, { number: 9, children: [{ number: 8, children: [] }] }] }];
当前问题代码
我目前编写的实现逻辑如下:
result.subscribe((x) => { this.phonebookTreeModel.items = {}; this.phonebookTreeModel.items.children = []; let array: any[] = []; x.items.forEach((item) => { console.log('items', item); if (item.parentId == 0 || item.parentId == null) { this.childrenArray = x.items.filter((i) => i.parentId == item.id); this.phonebookTreeModel.items.created = item.created; this.phonebookTreeModel.items.id = item.id; this.phonebookTreeModel.items.name = item.name; this.phonebookTreeModel.items.parentId = item.parentId; if (this.childrenArray.length > 0) { this.childrenArray.forEach((child) => { this.phonebookTreeModel.items.children.push(child); }); } array.push(this.phonebookTreeModel); } }); console.log('array is', array); });
接口返回的是扁平数组,每一项都带parentId字段标识父级ID。运行后最终生成的数组里重复存入了最后一项数据,执行结果参考截图:
接口返回的原始数据结构参考截图:
我最初以为是subscribe的异步特性导致的问题,但我不希望这段逻辑异步执行,该怎么解决?
问题根因
这个问题和异步特性完全无关,核心原因有两个:
- JavaScript中对象是引用类型,你在循环里全程修改的是同一个
this.phonebookTreeModel对象,push到数组里的都是这个对象的引用,后续循环修改对象属性时,之前存入数组的元素也会同步变化,最终所有元素都会显示最后一次循环赋值的内容 - 现有实现只处理了两层节点结构,无法生成你需要的多层嵌套树形结构
修复方案
不需要强行修改RxJS的异步逻辑,subscribe回调本身就是拿到接口返回数据后同步执行的,只需要解决对象引用问题、补全递归嵌套逻辑即可:
result.subscribe((x) => { const sourceList = x.items; // 递归生成任意层级树结构 const buildTree = (parentIdValue: number | null) => { return sourceList .filter(item => item.parentId == parentIdValue) .map(item => ({ ...item, // 拷贝当前项所有属性,生成独立新对象避免引用污染 children: buildTree(item.id) // 递归查询当前节点的子级 })) } // 兼容parentId为0和null两种根节点场景 const rootNodesForZeroId = buildTree(0); const rootNodesForNullId = buildTree(null); const finalTree = [...rootNodesForZeroId, ...rootNodesForNullId]; console.log('生成的树结构', finalTree); this.phonebookTreeModel.items = finalTree; });
实现说明
- 每次生成节点时都通过对象展开语法创建了独立的新对象,不存在复用同一个对象引用的问题,不会再出现所有项都是最后一条数据的情况
- 递归逻辑自动处理任意深度的节点嵌套,不需要手动编写多层循环查询子节点,生成的结构完全匹配你的目标格式
- 所有树结构生成逻辑都在拿到接口数据后同步执行,不存在异步时序问题
内容的提问来源于stack exchange,提问作者niki tmb
相关产品推荐
相关产品推荐

