Worker 通信 API 很简单,只有 postMessage 和 onmesssage 两个,Worker 通信 API 虽然简洁,但缺少易用性,增加了调试的困难,降低了排查问题的效率。
此前经过调研分析(调研报告),我司 Web Worker 方案基于 Comlink实现,但随着业务增长,单 worker 实例难以满足需求,因此着手探索 Web Worker 线程池方案实现,最终综合易用性,插件齐全,库包大小和兼容性等方面考虑,选择接入 threads.js
官方示例过于简单,以下是我司接入示例,以作参考:
- webpack 引入插件
const ThreadsPlugin = require('threads-plugin'); .... new ThreadsPlugin({ globalObject: 'self' }), .... - jsconfig.json / tsconfig.json / babel.config.js 响应配置(参考官方文档)
- 主文件 pool.ts
这里需要注意的是 Webpack5 引入 worker 文件存在一定 bug,必须使用如下语句:import { spawn, Pool, Worker } from 'threads'; // @ts-ignore import mainWorkerUrl from 'threads-plugin/dist/loader?name=main-worker!./worker/main.worker.ts'; const pool = Pool(() => spawn(new Worker(mainWorkerUrl)), 4); import type { PageList, RangeTime } from '#/player'; import type { LogList } from '#/dev-tool'; const getFormatLogSource = async (pages: PageList, logList: LogList, rangeTime: RangeTime) => { return pool.queue(worker => worker.formatLogSource(pages, logList, rangeTime)) } const logSearch = async (logList: LogList, payload: { type: string, searchKey: string }) => { return pool.queue(worker => worker.logSearch(logList, payload)) } export { getFormatLogSource, logSearch, }import mainWorkerUrl from 'threads-plugin/dist/loader?name=main-worker!./worker/main.worker.ts'; - worker 文件,main.worker.js
import { expose } from 'threads/worker'; import { formatLogSource, logSearch } from './modules/log'; expose({ formatLogSource, logSearch, }); - 具体业务文件,modules/log.ts
const logSearch = () => {}; const formatLogSource = () => {}; export { formatLogSource, logSearch, } - 其他业务,modules/xxxx.ts
- 应用
import { logSearch } from '@/worker-api/pool'; const runTask = async () => { const logList = await logSearch(); }import { xxx } from '@/worker-api/pool'; xxx().then(res => console.log(res));
运行结果