个人音乐网站建设,网店代运营的套路,网站开发 模块,ai网页界面设计文章目录 1、前言2、介绍 Web Worker3、使用须知及兼容性3.1、使用须知3.2、兼容性 4、使用 Web Worker4.1、创建 Web Worker4.2、与主线程通信4.3、终止 Web Worker4.4、监听错误信息 5、使用 Shared Worker4.5、调试 Shared Worker 6、使用中的一些坑6.1、Web Woeker 中引入了… 文章目录 1、前言2、介绍 Web Worker3、使用须知及兼容性3.1、使用须知3.2、兼容性 4、使用 Web Worker4.1、创建 Web Worker4.2、与主线程通信4.3、终止 Web Worker4.4、监听错误信息 5、使用 Shared Worker4.5、调试 Shared Worker 6、使用中的一些坑6.1、Web Woeker 中引入了其余文件6.2、在 WebPack 或 Vite 中使用6.2.1、webpack中使用5.2.2、vite中使用 5.3、sharedWorker的引入问题 7、后语 1、前言
最近做的项目出现了界面卡顿的问题经过一番排查发现是因为有个数据做了一些格式化和生成转换本来只有 1000 条数据处理完之后变成了 N 万条数据业务需求导致页面渲染很慢甚至会崩溃。于是就想着优化一下。初始化的时候不加载等需要的时候再使用 Web Worker 来处理数据避免主线程卡顿。
2、介绍 Web Worker
在介绍之前先说一下Web Worker是为什么而诞生的。
因为 JavaScript 语言采用的是单线程模型也就是说所有任务只能在一个线程上完成一次只能做一件事。前面的任务没做完后面的任务只能等着。随着电脑计算能力的增强尤其是多核 CPU 的出现单线程带来很大的不便无法充分发挥计算机的计算能力。
Web Worker 的作用就是为 JavaScript 创造多线程环境。它是 HTML5 标准的一部分它赋予了开发者利用 JavaScript 操作多线程的能力。允许主线程创建 Worker 线程将一些任务分配给 Worker 线程运行。在主线程运行的同时Worker 线程在后台运行两者互不干扰。等到 Worker 线程完成计算任务再把结果返回给主线程。这样的好处是一些计算密集型或高延迟的任务被 Worker 线程负担了主线程通常负责 UI 交互就会很流畅不会被阻塞或拖慢。
3、使用须知及兼容性
在使用 Worker 前需要先了解一些规则和浏览器的兼容性避免出现一些问题。
3.1、使用须知 资源耗费Worker 线程一旦新建成功就会始终运行不会被主线程上的活动比如用户点击按钮、提交表单打断。这样有利于随时响应主线程的通信。但是也造成了 Worker 比较耗费资源建议使用完毕就关闭。 同源限制分配给 Worker 线程运行的脚本文件必须与主线程的脚本文件同源。 DOM 限制Worker 线程所在的全局对象是 self它与主线程不一样无法读取主线程所在网页的 windowDOMdocumentparent 等全局对象但可以读取主线程的navigator 和 location 对象。 脚本限制Web Worker 中可以使用 XMLHttpRequest 和 Axios 发送请求。 通信联系Worker 线程和主线程不在同一个上下文环境它们不能直接通信必须通过消息完成。 文件限制Worker 线程中无法读取本地文件即不能打开本机的文件系统file://它所加载的脚本必须来自网络。
3.2、兼容性
浏览器兼容性最低兼容版本Chrome完全兼容4.0 (2008 年)Firefox完全兼容3.5 (2009 年)Safari完全兼容3.1 (2007 年)Edge完全兼容79 (2020 年)IE部分兼容10 (2012 年)Opera完全兼容10.5 (2010 年)
4、使用 Web Worker
直接使用 JavaScript 原生的 Worker()构造函数它的参数如下
参数说明path有效的 js 脚本的地址必须遵守同源策略options.type可选。用以指定 worker 类型。该值可以是 classic 或 module默认 classicoptions.credentials可选。指定 worker 凭证。该值可以是 omit, same-origin或 include。如果未指定或者 type 是 classic将使用默认值 omit (不要求凭证)options.name可选。在 DedicatedWorkerGlobalScope 的情况下用来表示 worker 的 scope 的一个 DOMString 值主要用于调试目的。
4.1、创建 Web Worker
主线程
const myWorker new Worker(/worker.js)// 接收消息
myWorker.addEventListener(message, (e) {console.log(e.data)
})// 向 worker 线程发送消息
myWorker.postMessage(Greeting from Main.js)4.2、与主线程通信
worker 线程
// 接收到消息
self.addEventListener(message, (e) {console.log(e.data)
})// 一顿计算后 发送消息
const calculateDataFn () {self.postMessage(ok)
}4.3、终止 Web Worker
两个线程里都可以操作自由选择。
在主线程中操作
// 创建worker
const myWorker new Worker(/worker.js)
// 关闭worker
myWorker.terminate()在 worker 线程中操作
self.close()4.4、监听错误信息
Web Worker 提供了两个事件监听错误回调error 和 messageerror。
事件描述error当 worker 内部出现错误时触发messageerror当 message 事件接收到无法被反序列化的参数时触发
在主线程中操作
// 创建worker
const myWorker new Worker(/worker.js)myWorker.addEventListener(error, (err) {console.log(err.message)
})myWorker.addEventListener(messageerror, (err) {console.log(err.message)
})在 worker 线程
self.addEventListener(error, (err) {console.log(err.message)
})
self.addEventListener(messageerror, (err) {console.log(err.message)
})5、使用 Shared Worker
SharedWorker 允许多个页面共享同一个后台线程从而实现更高效的资源利用和协同计算。如下是一个例子page1 和 page2 共享一个后台线程
sharedWorker.js
/*** description 所有连接这个worker的集合*/
const portsList []/*** description 连接成功回调*/
self.onconnect (event) {// 当前触发连接的端口const port event.ports[0]// 添加进去portsList.push(port)// 接收到消息的回调port.onmessage (event) {// 获取传递的消息const { message, value } event.data// 计算let result 0switch (message) {case add:result value * 2breakcase multiply:result value * valuebreakdefault:result value}// 给所有连接的目标发送消息portsList.forEach((port) port.postMessage(${message}结果是${result}))}
}sharedWorkerHook.js
const sharedWorker new SharedWorker(new URL(../../utils/webworker.js, import.meta.url), test)export default sharedWorkerpage1
templatediv clicksendMessage点击1/div
/templatescript
import sharedWorkerHook from ./sharedWorkerHookexport default {name: ,data() {return {}},computed: {},created() {},mounted() {sharedWorkerHook.port.start()// 接收SharedWorker返回的结果sharedWorkerHook.port.onmessage event {console.log(event.data)}},methods: {sendMessage() {sharedWorkerHook.port.postMessage({ message: add, value: 1 })}}
}
/scriptpage2
templatediv clicksendMessage点击2/div
/templatescript
import sharedWorkerHook from ./sharedWorkerHookexport default {name: ,data() {return {}},computed: {},created() {},mounted() {sharedWorkerHook.port.start()// 接收SharedWorker返回的结果sharedWorkerHook.port.onmessage event {console.log(event.data)}},methods: {sendMessage() {sharedWorkerHook.port.postMessage({ message: multiply, value: 1 })}}
}
/script4.5、调试 Shared Worker
sharedWorker 中调试使用 console 打印信息不会出现在主线程的的控制台中需要在 Chrome 浏览器地址栏输入 chrome://inspect/进入调试面板才能看到步骤如下
在 Chrome 浏览器地址栏输入 chrome://inspect并回车进入左边菜单栏点击 sharedWorker右边菜单栏点击 inspect即可打开调试面板 6、使用中的一些坑
在使用中虽然查阅了一些文档和博客但是还是出现了以下问题记录一下。
6.1、Web Woeker 中引入了其余文件
有一些场景需要放到 worker 进程去处理的任务很复杂就会引入其余文件这时候可以在worker线程中利用importScripts()方法加载我们需要的js文件
importScripts(./utils.js)如果引入的是ESModule模式需要在初始化的时候指定type的模式。
const worker new Worker(/worker.js, { type: module })6.2、在 WebPack 或 Vite 中使用
在webpack和vite中使用步骤如下
6.2.1、webpack中使用
第一步安装插件worker-plugin
npm install worker-plugin -D第二步在vue.config.js的configureWebpack.plugins中配置
const WorkerPlugin require(worker-plugin)module.exports {outputDir: dist,// 其余配置......configureWebpack: {devServer: {open: false,host: localhost,// 其余配置......},plugins: [// 其余配置......new WorkerPlugin()]}
}第三步使用
const webWorker new Worker(new URL(../utils/worker.js, import.meta.url), {type: module
})5.2.2、vite中使用
第一步安装插件worker-plugin
npm install worker-plugin -D第二步在vite.config.js的plugins中配置
import worker from worker-pluginconst viteConfig defineConfig((mode: ConfigEnv) {return {plugins: [vue(), worker()],server: {host: 0.0.0.0,port: 7001,open: true}}
})export default viteConfig第三步使用
const webWorker new Worker(new URL(../utils/worker.ts, import.meta.url), {type: module
})5.3、sharedWorker的引入问题
在使用sharedWorker的过程中发现sharedWorker进程里始终只有一个实例但是我确实在几个页面都初始化了同一个sharedWorker的js文件最后调试发现原因是通过插件引入之后名字变了一个是xxxx0.js一个是xxxx1.js所以导致我每次初始化的时候都不认为是同一个实例所以消息无法同步。
解决办法如[使用 Shared Worker](#5-使用 Shared Worker)里的例子一样专门用一个文件new好这个sharedWorker然后导出在需要的页面导入后再执行即可。
如
7、后语
在本文中我们学习了Web Worker的作用和使用方法以及如何在Vue中使用Web Worker最后我们还学习了Shared Worker的使用方法。
其实webworker家族里还有一位更加强大的成员那就是Service Worker。它可以做的东西很多比如拦截全局的fetch事件、缓存静态资源/离线缓存用于首屏加载、后台同步消息推送等等奈何篇幅有限下回再做讲解。 本次分享就到这儿啦我是鹏多多如果您看了觉得有帮助欢迎评论关注点赞转发我们下次见~
往期文章
Vue2全家桶Element搭建的PC端在线音乐网站vue3element-plus配置cdn助你上手Vue3全家桶之Vue3教程助你上手Vue3全家桶之VueX4教程助你上手Vue3全家桶之Vue-Router4教程超详细Vue的九种通信方式超详细Vuex手把手教程使用nvm管理node.js版本以及更换npm淘宝镜像源vue中利用.env文件存储全局环境变量以及配置vue启动和打包命令超详细Vue-Router手把手教程
个人主页
CSDNGitHub简书博客园掘金