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

如何基于RXJS实现树节点递归全展开且不修改源数据

解决方案

核心思路是调整递归函数的返回值为单个完整节点的Observable,全程通过浅拷贝组装新节点,完全不修改原始数据,同时简化了管道逻辑。

完整实现代码

类型定义(补充)

interface Node {
  id: number;
  parent: boolean;
  children?: Node[];
  // 可扩展其他原有属性
}
// 原有服务请求方法保持不变
declare function getChildrenFromServer(nodeId: number): Observable<Node[]>;

核心递归加载方法

/**
 * 递归加载单个节点的完整层级结构,返回新的节点对象,不修改输入的原始节点
 */
function loadFullNode(originalNode: Node): Observable<Node> {
  // 非父节点直接返回浅拷贝,无需请求子节点
  if (!originalNode.parent) {
    return of({ ...originalNode });
  }
  return getChildrenFromServer(originalNode.id).pipe(
    // 并行递归加载所有子节点的完整结构
    mergeMap(children => forkJoin(
      (children || []).map(child => loadFullNode(child))
    )),
    // 组装新节点,无任何副作用
    map(fullChildren => ({
      ...originalNode,
      ...(fullChildren.length ? { children: fullChildren } : {})
    }))
  );
}

调用方式

// 原始根节点,全程不会被修改
const rootNodes = [{ id: 0, parent: true }, { id: 1000, parent: true }];
// 加载整棵树
forkJoin(rootNodes.map(node => loadFullNode(node)))
  .subscribe(fullTree => {
    // 输出完整树结构
    console.log(fullTree);
    // 验证原始数据未被修改
    console.log(rootNodes);
  });

优化点说明

  • 无副作用:所有节点操作都基于浅拷贝生成新对象,完全不改动原始输入数据
  • 逻辑简化:移除了原实现中filter、tap等副作用操作,递归逻辑和数据组装逻辑拆分清晰
  • 加载效率不变:同级节点的请求保持并行发起,和原实现加载效率一致
  • 扩展性更好:可直接在loadFullNode中添加单个节点的加载错误兜底、超时等逻辑,不影响全局

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 03:48:03