封装一个web Worker 处理方法实现多线程
背景:
开启多线程处理一段耗时的逻辑
简化Worker使用
直接上代码:
以下是封装的函数直接复制即可
/**
* 封装一个worker的启动函数 用于开启一个新的线程 来处理一些耗时的操作
* @param {object} paremdata 传递给worker的参数
* @param {function} callbackFun 回调函数
* @param {function} getDataCallback 接收worker返回的数据的回调函数
*/
function worderHandle ({
paremdata = {},
callbackFun = () => { },
getDataCallback = () => { },
}) {
const myWorker = new Worker(funToBlobURL(worderFun))
// 监听来自Worker的消息
let data = {}
myWorker.onmessage = function (e) {
// console.log('收到来自Worker的消息:', e.data)
getDataCallback(e.data)
}
myWorker.postMessage({
data: {
...paremdata,
},
callbackFuns: callbackFun.toString()
})
// 此处的变量与外侧全局变量隔离 无法访问到的
function worderFun () {
self.onmessage = async function (e) {
// console.log('收到来自主线程的消息:', e.data)
let callbackFuns = eval(e.data.callbackFuns)
try {
let pdata = await callbackFuns(e.data.data)
self.postMessage(pdata)
} catch (error) {
self.postMessage(error)
}
}
}
/**
* 函数转异步链接
* @param {string} message 要发送的消息
*/
function funToBlobURL (fun) {
if (!fun) {
return ''
}
/**
* 将文本内容转换为Blob URL
* @param {string} textContent 文本内容
* @returns {string} Blob URL
*/
function txtToBlobURL (textContent = '这是一段示例文本') {
// 创建Blob对象,指定MIME类型为'text/plain'
const blob = new Blob([textContent], { type: 'text/plain' })
// 创建指向该Blob对象的URL
const blobUrl = URL.createObjectURL(blob)
// console.log(blobUrl) // 输出Blob URL
// 当不再需要Blob URL时
setTimeout(() => {
URL.revokeObjectURL(blobUrl)
}, 0)
return blobUrl
}
return txtToBlobURL(`(${fun.toString()})()`)
}
}
用法示例
let workData = {
paremdata: { // 传入的初始参数
a: 123,
},
callbackFun: (res) => {
// 接收的是paremdata 的数据 由于 worder函数是独立的所以必须使用这种方式 注意此处无法访问当前环境的任何参数,只能使用 res 因此你必须在paremdata 传到这个函数才行 此方法支持同步和异步。一般耗时操作多为异步
console.log('回调函数执行', res)
return new Promise((resolve, reject) => {
setTimeout(() => {
// reject('出错了')
resolve(res.a + 100)
}, 5000)
})
},
getDataCallback: (res) => {
// 接收callbackFun 返回的结果的 then和catch 都会到这里。 如果想区分可修改上面的方法。来满足自身的需求
console.log('接收到的数据 getDataCallback执行', res)
}
}
worderHandle(workData)
如有问题,可提出,共勉
注意:
该方法暂未做兼容,以下是兼容浏览器。
目测大部分主流浏览器都支持的。也无伤大雅