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

Web浏览器创建Worker:解决Viewer内存密集型任务卡顿问题

将Viewer内存密集型任务移至Web Worker的实现方案

1. 编写Worker处理脚本(worker.js)

Worker运行在独立线程,不会阻塞主页面的Viewer渲染和交互。以下是基础的Worker实现,负责接收元素数据、执行密集计算并返回结果:

// worker.js
self.addEventListener('message', async (event) => {
  try {
    const { elementProperties } = event.data;
    // 替换为你的内存密集型处理逻辑,比如遍历统计、数据清洗等
    const processedData = handleElementProcessing(elementProperties);
    
    // 将处理结果回传给主线程
    self.postMessage({ type: 'success', payload: processedData });
  } catch (error) {
    // 捕获处理过程中的错误,避免Worker崩溃
    self.postMessage({ type: 'error', message: error.message });
  }
});

// 自定义的密集型处理函数示例
function handleElementProcessing(propertiesList) {
  const categoryCount = {};
  propertiesList.forEach(item => {
    const category = item.properties?.Category?.value || '未分类';
    categoryCount[category] = (categoryCount[category] || 0) + 1;
  });
  return categoryCount;
}

2. 主线程(Viewer页面)集成Worker

在Viewer初始化完成后,创建Worker实例,从Viewer提取可序列化的元素数据并传递给Worker,同时监听结果返回:

// 主线程代码,需在Viewer加载完成后执行
let elementWorker = null;

// 初始化Worker
function setupWorker() {
  elementWorker = new Worker('worker.js');
  
  // 监听Worker返回的消息
  elementWorker.addEventListener('message', (event) => {
    switch (event.data.type) {
      case 'success':
        console.log('处理结果:', event.data.payload);
        // 在此处更新页面UI或执行后续操作,不阻塞Viewer
        break;
      case 'error':
        console.error('Worker处理出错:', event.data.message);
        break;
    }
  });
  
  // 监听Worker自身的错误
  elementWorker.addEventListener('error', (error) => {
    console.error(`Worker异常:${error.message},行号:${error.lineno}`);
  });
}

// 提取Viewer元素数据并发送给Worker
async function dispatchElementData() {
  if (!elementWorker) setupWorker();
  
  try {
    // 获取Viewer模型的所有元素ID
    const modelData = viewer.model.getData();
    const allDbIds = [];
    modelData.instanceTree.enumNodeChildren(modelData.instanceTree.getRootId(), (dbId) => {
      allDbIds.push(dbId);
    }, true);
    
    // 批量获取元素属性(按需指定字段,减少数据传输量)
    const elementProps = await viewer.getBulkProperties(allDbIds, ['Category', 'Family', 'Name'], true);
    
    // 传递可序列化的数据给Worker
    elementWorker.postMessage({ elementProperties: elementProps });
  } catch (err) {
    console.error('提取Viewer元素数据失败:', err);
  }
}

// 页面卸载时销毁Worker,避免内存泄漏
window.addEventListener('beforeunload', () => {
  if (elementWorker) {
    elementWorker.terminate();
    elementWorker = null;
  }
});

3. 核心优化要点

  • 数据序列化限制:Web Worker仅支持传递JSON可序列化数据,不能直接传递Viewer的复杂对象(如模型实例),必须先提取原始属性值、ID等基础数据再传递。
  • 分批次处理:若元素数量过万,一次性传递所有数据会增加内存压力,可将ID数组拆分成分组,分批发送给Worker处理,降低单次数据传输量。
  • Worker复用:避免频繁创建销毁Worker,单实例复用即可;无需Worker时调用terminate()销毁,防止内存泄漏。
  • 异步交互:主线程发送数据后通过message事件异步接收结果,不要使用同步阻塞逻辑,确保Viewer的渲染和交互流畅。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 13:05:23