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
相关产品推荐
相关产品推荐

