为什么要使用 web-workers
原因很简单,将复杂的计算逻辑和耗时逻辑放到线程中运行,避免ui阻塞,防止卡顿问题
场景:本次运用于GPS 位置更新
接入小程序
注意事项:微信小程序中只允许存在一个 worker所以,需要再一个worker里面完成多个任务,或者在开心的woker时,需要关闭当前的worker
一,在static/workers 下放你需要的worker.js文件
gps-workers.js
//用于接收外部消息
worker.onMessage(function (res) {console.log('worker内部线程')console.log(res)//用于发送// worker.postMessage({// message: '收到worker的消息'// });const { type, data } = res;let result;switch (type) {case 'PROCESS_GPS_DATA': {result = processGpsData(res.data);break;}case 'PROCESS_POSITION': {result = filterPlayerPositions(data);break;}}worker.postMessage({data: result,type,});
});
// 处理GPS数据
function processGpsData(data) {// 业务代码return data
}
// 筛选用户
function filterPlayerPositions(data) {// 业务代码return data
}
二,在pages.json中配置workers目录
三,在页面引入使用
// 注册
// #ifdef MP
let worker: UniApp.Worker | null = null
try {worker = uni.createWorker('static/workers/gps-workers.js', {useExperimentalWorker: true,})worker.onMessage((res) => {const { type, data } = resconsole.log('Worker 收到消息:', data)switch (type) {case WebWorkerTypeEnum.PROCESS_GPS_DATA:// 业务代码breakcase WebWorkerTypeEnum.PROCESS_POSITION:// 业务代码break}})
} catch (e) {console.error('创建 Worker 失败:', e)
}
// #endif// 发现消息给web-worker处理worker?.postMessage({data: {positions: cloneDeep(positionBsResult.list),players: cloneDeep(players.value),},type: WebWorkerTypeEnum.PROCESS_GPS_DATA,})
// 释放
onUnload(() => {worker?.terminate()
})
优化后的对标
接入web
在未更改前,由于数据量大,信息更新除了接口请求,耗时在7s+,ui会卡顿,特别是第一次加载数据以及位置更新的时候,后面优化后基本达到毫秒级别
一,在适合的目录创建
gps-worker.ts
// 处理 GPS 数据的逻辑
function processGpsData(data) {// 业务代码。。。return data
}// 添加新的 worker 处理函数
function filterPlayerPositions(data: xxx) {// 业务代码。。。return data
}// 修改消息监听方式
globalThis.addEventListener('message', (e) => {const { type, data } = e.data;let result: any;switch (type) {case WebWorkerTypeEnum.PROCESS_GPS_DATA: {result = processGpsData(data);break;}case WebWorkerTypeEnum.PROCESS_POSITION: {result = filterPlayerPositions(data);break;}}globalThis.postMessage({data: result,type,});
});
// export default {} as typeof Worker & { new (): Worker };
export default null;
二,在需要的位置加载和使用
// 加载web workerworker.value = new Worker(new URL('../data/gps-worker.ts', import.meta.url), {type: 'module',});worker.value.addEventListener('message', (e) => {const { type, data } = e.data;if (type === WebWorkerTypeEnum.PROCESS_GPS_DATA) {// 处理 worker 返回的数据}});
总结
- 合理利用web-worker处理复杂的数据,特别是数据两比较大的更新