/**
* Web Worke 封装
* @param task 耗时任务function (task 必须为纯函数,且不可使用外部变量或调用外部函数)
* @param deps task任务执行依赖
* @returns Promise<T>
*/
export function executeTaskByWorker<T = any>(task: () => T, deps?: Record<string, any>): Promise<T> {
const dependencies = Object.keys(deps || {})
.map(key => {
if (typeof deps?.[key] === 'function') {
return deps[key].toString()
}
return `const ${key} = ${JSON.stringify(deps?.[key])};`
})
.join('\n\n')
return new Promise((resolve, reject) => {
const blob = new Blob(
[
`
${dependencies || ''}
onmessage = function(e) {
const taskResult = (${task.toString()})();
postMessage(taskResult);
};
`,
],
{ type: 'application/javascript' },
)
const worker = new Worker(URL.createObjectURL(blob))
worker.postMessage('')
worker.onmessage = (e: any) => {
resolve(e.data)
worker.terminate()
}
worker.onerror = (err: unknown) => {
reject(err)
worker.terminate()
}
})
}
example:
import { executeTaskByWorker } from './utils'
const sendWorker = (data: any) => {
const taskDepData = data || []
const deps = {
taskDepData,
}
executeTaskByWorker(() => {
const options = taskDepData.map(item => {
//... 使用 Web Worker 执行耗时任务
return {
...item,
label: item.label,
value: item.id,
}
})
return options
}, deps).then((res: any) => {
console.log("🚀 ~ executeTaskByWorker ~ res:", res)
})
}
打包时,会混淆变量名导致依赖参数无法找到,改一下使用方式
export function executeTaskByWorker<T = any>(task: string, deps?: Record<string, any>): Promise<T> {
const dependencies = Object.keys(deps || {})
.map(key => {
if (typeof deps?.[key] === 'function') {
return deps[key].toString()
}
return `const ${key} = ${JSON.stringify(deps?.[key])};`
})
.join('\n\n')
return new Promise((resolve, reject) => {
const blob = new Blob(
[
`
${dependencies || ''}
onmessage = function(e) {
const taskResult = (${task})();
postMessage(taskResult);
};
`,
],
{ type: 'application/javascript' },
)
const worker = new Worker(URL.createObjectURL(blob))
worker.postMessage('')
worker.onmessage = (e: any) => {
resolve(e.data)
worker.terminate()
}
worker.onerror = (err: unknown) => {
reject(err)
worker.terminate()
}
})
}
example:
import { executeTaskByWorker } from './utils'
const sendWorker = (data: any) => {
const taskDepData = data || []
const deps = {
taskDepData,
}
const task = `() => {
const options = taskDepData.map(item => {
//... 使用 Web Worker 执行耗时任务
return {
...item,
label: item.label,
value: item.id,
}
})
return options
}`
executeTaskByWorker(task, deps).then((res: any) => {
console.log("🚀 ~ executeTaskByWorker ~ res:", res)
})
}
网友评论