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

如何实现树形对象系统中嵌套属性子集解析完成的回调监听

树形对象系统watch3方法实现方案

需求回顾

现有树形对象系统中,原watch方法仅在节点所有子属性完成解析(resolved)时触发回调。需扩展实现watch3方法,支持通过类GraphQL的Matcher语法匹配嵌套属性子集,当该子集所有属性解析完成时触发回调,同时满足:

  • 若添加监听前目标子集已全部解析,立即触发回调
  • 若添加监听后目标子集逐步完成解析,待全部完成时触发回调

核心实现思路

  1. Matcher语法解析:将类GraphQL结构的Matcher转换为扁平化的属性路径集合(如{ a, b: { c, d } }转换为['a', 'b.c', 'b.d'])
  2. 状态追踪与触发判断:为每个监听任务维护已完成解析的路径计数,当计数等于总路径数时执行回调
  3. 即时检查机制:添加监听时遍历所有目标路径,统计已resolved的数量,若全部完成则立即执行回调
  4. 动态监听绑定:对未resolved的路径,绑定对应节点的解析完成事件,每完成一个路径就更新计数,直至全部完成后触发回调并清理监听

代码实现

假设现有系统基础结构如下:

class TreeNode {
  constructor() {
    this.resolved = false;
    this.children = new Map();
    this.onResolvedCallbacks = [];
  }

  // 获取指定路径的节点,路径格式如'a.b.c'
  get(path) {
    let current = this;
    for (const key of path.split('.')) {
      if (!current.children.has(key)) return null;
      current = current.children.get(key);
    }
    return current;
  }

  // 标记当前节点为已解析,并触发回调
  resolve() {
    if (this.resolved) return;
    this.resolved = true;
    this.onResolvedCallbacks.forEach(cb => cb());
  }

  // 监听节点解析完成事件
  onResolved(callback) {
    if (this.resolved) {
      callback();
      return;
    }
    this.onResolvedCallbacks.push(callback);
  }
}

实现watch3及辅助方法

class TreeWatcher {
  constructor(rootNode) {
    this.root = rootNode;
  }

  // 解析Matcher为扁平化路径集合
  parseMatcher(matcher) {
    const paths = [];

    function traverse(obj, parentPath = '') {
      for (const [key, value] of Object.entries(obj)) {
        const currentPath = parentPath ? `${parentPath}.${key}` : key;
        if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
          traverse(value, currentPath);
        } else {
          paths.push(currentPath);
        }
      }
    }

    traverse(matcher);
    return paths;
  }

  // 核心watch3方法
  watch3(matcher, callback) {
    const targetPaths = this.parseMatcher(matcher);
    if (targetPaths.length === 0) {
      callback();
      return;
    }

    let resolvedCount = 0;
    const totalPaths = targetPaths.length;
    const cleanupFns = [];

    // 检查单个路径的解析状态,并绑定监听
    const checkAndWatchPath = (path) => {
      const node = this.root.get(path);
      if (!node) {
        // 路径不存在时默认标记为完成,可根据需求调整为抛出错误或其他逻辑
        resolvedCount++;
        checkIfAllResolved();
        return;
      }

      if (node.resolved) {
        resolvedCount++;
        checkIfAllResolved();
        return;
      }

      // 绑定解析完成监听
      const onResolved = () => {
        resolvedCount++;
        checkIfAllResolved();
      };
      node.onResolved(onResolved);
      cleanupFns.push(() => {
        const index = node.onResolvedCallbacks.indexOf(onResolved);
        if (index !== -1) node.onResolvedCallbacks.splice(index, 1);
      });
    };

    // 判断是否所有路径已解析完成
    const checkIfAllResolved = () => {
      if (resolvedCount === totalPaths) {
        callback();
        // 清理所有监听
        cleanupFns.forEach(fn => fn());
      }
    };

    // 遍历所有目标路径,初始化检查与监听
    targetPaths.forEach(checkAndWatchPath);
  }
}

场景验证

场景1:添加监听前属性已全部解析

// 构建已解析完成的树
const root = new TreeNode();
const nodeA = new TreeNode();
nodeA.resolve();
root.children.set('a', nodeA);

const nodeB = new TreeNode();
const nodeBC = new TreeNode();
nodeBC.resolve();
nodeB.children.set('c', nodeBC);
nodeB.resolve();
root.children.set('b', nodeB);

const watcher = new TreeWatcher(root);
// 监听子集{a, b: {c}}
watcher.watch3({ a: true, b: { c: true } }, () => {
  console.log('子集已全部解析完成(场景1)');
});
// 输出:子集已全部解析完成(场景1)

场景2:添加监听后属性逐步解析完成

const root = new TreeNode();
const nodeA = new TreeNode();
root.children.set('a', nodeA);

const nodeB = new TreeNode();
const nodeBD = new TreeNode();
nodeB.children.set('d', nodeBD);
root.children.set('b', nodeB);

const watcher = new TreeWatcher(root);
// 监听子集{a, b: {d}}
watcher.watch3({ a: true, b: { d: true } }, () => {
  console.log('子集已全部解析完成(场景2)');
});

// 逐步解析节点
setTimeout(() => nodeA.resolve(), 1000);
setTimeout(() => nodeBD.resolve(), 2000);
// 2秒后输出:子集已全部解析完成(场景2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 04:42:42