关于在 vue 中使用 web worker 的一些问题
首先列出碰到的问题和答案好了好了:
1、如何在 vue 中加载 worker.js 文件:
使用 worker-loader,并在 vue.config.js 文件中做出相应配置,具体规则参考正文
2、如何在 worker.js 中使用 import:
如果使用 vue,那第一个问题就顺带解决了这个问题。
如果不用,则需要在创建 Worker 对象的时候,第二个参数填写上 { type: 'module' }。例:new Worker('./worker.js', { type: 'module' })
3、如何将 worker 的 message 事件变成 async/await
使用 promise-worker 包,具体使用方式参考下方或者 npm 文档
前几天,测试给提了一个问题,说是在一个页面点击按钮后,界面会卡顿十几秒。我检查代码后发现,是加密信息时,加密内容过大,导致了程序卡顿,尝试降低了加密内容大小,将卡顿时间压缩到二到四秒。但是用起来还是怪怪的,突然想到从来没有用过的 worker,用这个不就可以不阻塞渲染进程了嘛,何不乘此机会用一次呢?于是便开始翻阅 MDN 的相关文档。
按照 MDN 的示例代码,我尝试编写完 worker.js,并调用了 new Worker('./worker.js'),但是控制台提示,找不到该文件,我上 stock overflow 查了查。一开始以为是没使用模块的问题,便尝试将 new Worker('./worker.js') 改成了 new Worker('./worker.js', { type: 'module' }),但是还是没用。
换了关键词后,发现可能需要使用 webpack 的插件加载 worker.js,便去翻了 webpack 4 的 worker loader 的使用方法。官方文档说,按照官方文档的最简配置,我修改了 vue.config.js,但是没有效果,便去 stock overflow 上搜索。试了几种方法后,最后发现可能需要先移除 js 规则检查,移除检查后,再次运行,便可以运行了。
解决了无法加载的问题之后,我便尝试获取 worker 线程的返回值了,看了看文档,发现,不能实现我想要的同步效果,便去找使用 promise 的 worker 包,然后就找到了 promise-worker。按照官方文档所述,代码终于成功运行了,可喜可贺可喜可贺。下面是示例代码:
// vue.config.js let config = { chainWebpack: (config) => { config.module.rule('js').exclude.add(/\.worker\.js$/).end() config.module .rule('worker') .test(/\.worker\.(c|m)?js$/i) .use('worker-loader') .loader('worker-loader') .options({ inline: 'fallback', }) .end(); }, }; module.exports = config; // example.worker.js import { doEncrypt } from 'utils.js' import registerPromiseWorker from 'promise-worker/register'; registerPromiseWorker(({ message }) => doEncrypt (message); // example.js import Worker from './example.worker.js'; const worker = new Worker() const exampleWorker = new PromiseWorker(worker); /** * 发布消息 * @param {Object} wsClient * @param {string} message * @param {object} payload */ export const sendMessage = async (wsClient,message)=>{ const encryptString = await exampleWorker?.postMessage({ message }).catch((error) => console.error(error))) wsClient.send(encryptString) }