Web Woeker和Shared Worker的使用以及案例

文章目录

  • 1、前言
  • 2、介绍 Web Worker
  • 3、使用须知及兼容性
    • 3.1、使用须知
    • 3.2、兼容性
  • 4、使用 Web Worker
    • 4.1、创建 Web Worker
    • 4.2、与主线程通信
    • 4.3、终止 Web Worker
    • 4.4、监听错误信息
  • 5、使用 Shared Worker
    • 4.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、使用须知

  1. 资源耗费:Worker 线程一旦新建成功就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是也造成了 Worker 比较耗费资源,建议使用完毕就关闭。

  2. 同源限制:分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

  3. DOM 限制:Worker 线程所在的全局对象是 self,它与主线程不一样,无法读取主线程所在网页的 window,DOM,document,parent 等全局对象,但可以读取主线程的:navigator 和 location 对象。

  4. 脚本限制:Web Worker 中可以使用 XMLHttpRequest 和 Axios 发送请求。

  5. 通信联系:Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。

  6. 文件限制: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,默认 classic
options.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 允许多个页面共享同一个后台线程,从而实现更高效的资源利用和协同计算。如下,是一个例子,page1page2 共享一个后台线程:

  • 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 sharedWorker
  • page1
<template><div @click="sendMessage">点击1</div>
</template><script>
import sharedWorkerHook from './sharedWorkerHook'export 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 })}}
}
</script>
  • page2
<template><div @click="sendMessage">点击2</div>
</template><script>
import sharedWorkerHook from './sharedWorkerHook'export 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 })}}
}
</script>

4.5、调试 Shared Worker

sharedWorker 中调试,使用 console 打印信息,不会出现在主线程的的控制台中,需要在 Chrome 浏览器地址栏输入 chrome://inspect/,进入调试面板才能看到,步骤如下:

  1. 在 Chrome 浏览器地址栏输入 chrome://inspect,并回车进入
  2. 左边菜单栏,点击 sharedWorker
  3. 右边菜单栏,点击 inspect,即可打开调试面板

调试 Shared Worker

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-plugin'const 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端在线音乐网站
  • vue3+element-plus配置cdn
  • 助你上手Vue3全家桶之Vue3教程
  • 助你上手Vue3全家桶之VueX4教程
  • 助你上手Vue3全家桶之Vue-Router4教程
  • 超详细!Vue的九种通信方式
  • 超详细!Vuex手把手教程
  • 使用nvm管理node.js版本以及更换npm淘宝镜像源
  • vue中利用.env文件存储全局环境变量,以及配置vue启动和打包命令
  • 超详细!Vue-Router手把手教程

个人主页

  • CSDN
  • GitHub
  • 简书
  • 博客园
  • 掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/161431.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode】【每日一题】【中等】187. 重复的DNA序列 官方题解待更新

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/repeated-dna-sequences/descrip…

带斜杠的能读出来,不带斜杠的读不出来,为什么?

能读出来。 读不出来&#xff0c;为什么呢&#xff1f;

高效处理文件:批量顺序编号重命名方法

每个人都面临着文件管理的挑战&#xff0c;特别是那些需要处理大量文件的人。如何高效地管理这些文件一直是一个难题。为了解决这个问题&#xff0c;我向大家推荐一款强大的文件管理工具——固乔文件管家。这个工具可以帮助你快速有效地给文件进行批量重命名和编号&#xff0c;…

《基于先验未知盲反卷积技术的包络谱重复瞬态的循环平稳性提取》阅读笔记及代码整理

论文阅读笔记及代码整理 《Extracting cyclo-stationarity of repetitive transients from envelope spectrum based on prior-unknown blind deconvolution technique》 代码有优化整理过&#xff0c;需要请下载&#xff1a;https://mbd.pub/o/bread/ZZaTl5ht 贡献&#xff1…

Ubuntu连不上WiFi 或者虽然能连上校园网,但是浏览器打不开登录页面

写在前面 自己的电脑环境&#xff1a; Ubuntu20.04 一、问题描述 自己的 Ubuntu 遇到连接不上 除校园网之外的其他WiFi, 或者 虽然能连上校园网&#xff0c;但是浏览器打不开登录页面的问题。 二、解决方法 出现这种问题的原因可能是 之前开过VPN, 导致系统的网络设置出现…

0基础学习VR全景平台篇第117篇:利用插件地拍补地 - PS教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 嗨&#xff0c;大家好&#xff0c;今天我们来介绍【PS利用插件地拍补地】。 之前已经教给大家补地插件的安装方法&#xff0c;今天我们教给大家如何使用这个插件进行补地。 首…

基于卷尾猴算法的无人机航迹规划-附代码

基于卷尾猴算法的无人机航迹规划 文章目录 基于卷尾猴算法的无人机航迹规划1.卷尾猴搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用卷尾猴算法来优化无人机航迹规划。 1.卷尾猴…

差生文具多之(一)eBPF

前言 在问题排查过程中, 通常包含: 整体观测, 数据采集, 数据分析这几个阶段. 对于简单问题的排查, 可以跳过前两个步骤, 无需额外收集数据, 直接通过分析日志中的关键信息就可以定位根因; 而对于复杂问题的排查, 为了对应用的行为有更完整的了解, 可以通过以下形式收集更多的…

嵌入式中如何将BootLoader与APP合并成一个固件

1、前言 嵌入式固件一般分为BootLoader和App&#xff0c;BootLoader用于启动校验、App升级、App版本回滚等功能&#xff0c;BootLoader在cpu上电第一阶段中运行&#xff0c;之后跳转至App地址执行应用程序。 因此&#xff0c;在发布固件的时候&#xff0c;会存在BootLoader固件…

野火霸天虎 STM32F407 学习笔记_1 stm32介绍;调试方法介绍

STM32入门——基于野火 F407 霸天虎课程学习 前言 博主开始探索嵌入式以来&#xff0c;其实很早就开始玩 stm32 了。但是学了一段时间之后总是感觉还是很没有头绪&#xff0c;不知道在学什么。前前后后分别尝试了江协科技、正点原子、野火霸天虎三次 stm32 的课程学习。江协科…

【qemu逃逸】HWS2017-FastCP

前言 虚拟机用户名&#xff1a;root 虚拟机密码&#xff1a;无密码 本题有符号&#xff0c;所以对于设备定位啥的就不多说了&#xff0c;直接逆向设备吧。 设备逆向 在 realize 函数中设置一个时钟任务&#xff0c;并且可以看到只注册了 mmio&#xff0c;大小为 0x100000。…

什么是DITA?从百度的回答说起

▲ 搜索“大龙谈智能内容”关注GongZongHao▲ 什么是DITA? 把这个问题输入百度&#xff0c;获得以下回答&#xff1a; DITA 是“Darwin Information Typing Architecture”&#xff08;达尔文信息类型化体系结构&#xff09;的缩写&#xff0c;它是IBM 公司为OASIS 所支持…