为什么要使用 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 } = res
console.log('Worker 收到消息:', data)
switch (type) {
case WebWorkerTypeEnum.PROCESS_GPS_DATA:
// 业务代码
break
case 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 worker
worker.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处理复杂的数据,特别是数据两比较大的更新