/**
* Web Worke 封裝
* @param task 耗時任務function (task 必須為純函數(shù),且不可使用外部變量或調(diào)用外部函數(shù))
* @param deps task任務執(zhí)行依賴
* @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 執(zhí)行耗時任務
return {
...item,
label: item.label,
value: item.id,
}
})
return options
}, deps).then((res: any) => {
console.log("?? ~ executeTaskByWorker ~ res:", res)
})
}
打包時,會混淆變量名導致依賴參數(shù)無法找到,改一下使用方式
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 執(zhí)行耗時任務
return {
...item,
label: item.label,
value: item.id,
}
})
return options
}`
executeTaskByWorker(task, deps).then((res: any) => {
console.log("?? ~ executeTaskByWorker ~ res:", res)
})
}