我用 @giszhc/worker-client + OpenLayers,硬是把 100 万点数据干流畅了(附在线示例)

张开发
2026/4/10 12:55:07 15 分钟阅读

分享文章

我用 @giszhc/worker-client + OpenLayers,硬是把 100 万点数据干流畅了(附在线示例)
我用 giszhc/worker-client OpenLayers硬是把 100 万点数据干流畅了别再抱怨 OpenLayers 卡了大概率是你把活全丢给主线程了…一、真实问题为什么我地图一上 10 万点就开始“抽搐”说个我自己踩过的坑。之前做一个 WebGIS 项目需要在地图上展示设备点位。一开始数据量还好几千条OpenLayers 跑得飞快。后来数据一上来10 万开始掉帧30 万拖地图像 PPT100 万直接怀疑人生浏览器要不你还是关了吧我当时第一反应是“OpenLayers 不行”后来发现——不是它不行是我把所有脏活累活都丢给了主线程。二、核心原因你卡不是因为“渲染”而是“计算”很多人会误以为地图卡 渲染慢其实更常见的是数据处理 坐标转换 构建 Feature 太耗 CPU比如你常写的代码constfeaturesdata.map(item{returnnewFeature({geometry:newPoint([item.lng,item.lat])});});看起来很正常对吧但如果是 100 万条 主线程直接被干爆因为JS 是单线程UI 渲染也在这个线程你一计算页面就“卡住呼吸”三、解决思路把计算丢进 Worker但别用原生理论上你可能会想到newWorker(worker.js)然后开始postMessageonmessage数据序列化debug 地狱写到一半就想“我只是想处理个数组至于吗”所以我后来自己搞了个库giszhc/worker-client核心思路就一句话 把 Worker 变成“函数调用”四、核心用法像调用函数一样用 Worker先看一个最关键的例子import{WorkerClient}fromgiszhc/worker-client;typeWorkerMethods{buildFeatures(data:any[]):any[];};constworkernewWorkerClientWorkerMethods({buildFeatures(data){returndata.map(item({coords:[item.lng,item.lat]}));}});// 主线程直接调用constresultawaitworker.buildFeatures(bigData);是不是很离谱没有 worker.js没有 postMessage直接 await五、实战OpenLayers 加载 100 万点1️⃣ Worker 里做“重活”constworkernewWorkerClient({buildPoints(data){returndata.map(item{return{coordinates:[item.lng,item.lat]};});}});2️⃣ 主线程只负责“渲染”constrawPointsawaitworker.buildPoints(bigData);constfeaturesrawPoints.map(p{returnnewFeature({geometry:newPoint(p.coordinates)});});vectorSource.addFeatures(features); 效果对比我实测方案体验全在主线程卡到怀疑人生Worker 分担基本流畅 本质不是“更快”而是UI 线程终于能喘气了六、再进阶分批加载这招更狠如果你直接一次性丢 100 万条 Feature 还是可能卡一瞬优化方案constchunkSize5000;for(leti0;irawPoints.length;ichunkSize){constchunkrawPoints.slice(i,ichunkSize);constfeatureschunk.map(p{returnnewFeature({geometry:newPoint(p.coordinates)});});vectorSource.addFeatures(features);awaitnewPromise(rsetTimeout(r,0));// 让出线程}效果 地图是“渐进加载”的 用户不会感觉卡死七、几个真实踩坑很重要❌ 1. Worker 里不能用外部变量constbase100;constworkernewWorkerClient({test(){returnbase;// ❌ undefined}}); 因为函数是toString进去的❌ 2. 不要在 Worker 里 new Feature很多人会写newFeature(...)❌ 直接报错因为Worker 没有 DOMOpenLayers 依赖浏览器环境 正确做法只返回“纯数据”❌ 3. 数据必须能结构化克隆可以ArrayObjectTypedArray不可以Functionclass 实例❌ 4. 别搞太复杂逻辑Worker 适合✔ 数据处理✔ 坐标转换✔ 批量计算不适合❌ UI逻辑❌ 地图操作八、为什么这个方案真的有用说白了就一句话把 CPU 密集任务从 UI 线程剥离浏览器其实是这样的主线程UI JSWorker计算专用你以前是主线程 渲染 计算爆炸现在是主线程 渲染 Worker 干活 九、顺便说一句小感悟很多人优化性能一上来就 Virtual DOM或者各种奇技淫巧但其实最本质的优化是别让主线程干太多事十、总结这套方案的核心其实很简单大数据处理 → 丢给 Worker主线程 → 只负责渲染分批加载 → 避免瞬时卡顿而 giszhc/worker-client 做的事情是把 Worker 从“难用 API”变成“普通函数”最后一句有点真心话我一开始写这个库其实就是因为被 postMessage 折磨烦了…现在回头看能让代码简单一点就是最大的性能优化至少对脑子来说懂的都懂写过原生 Worker 的应该已经在点头了在线示例我们提供了一个功能完整的在线演示页面您可以直接在浏览器中体验所有功能 立即体验点击访问在线演示如果这篇文章对你有帮助欢迎点赞 收藏 ⭐ 关注 完结撒花✿✿ヽ(°▽°)ノ✿

更多文章