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

news2024/11/27 23:31:18

文章目录

  • 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 = 0
		switch (message) {
			case 'add':
				result = value * 2
				break
			case 'multiply':
				result = value * value
				break
			default:
				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.coloradmin.cn/o/1160409.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第4章_运算符

文章目录 1. 算术运算符1.1 加法与减法运算符1.2 乘法与除法运算符1.3 求模运算符 2. 比较运算符2.1 等号运算符2.2 安全等于运算符2.3 不等于运算符2.4 空运算符2.5 非空运算符2.6 最小值运算符2.7 最大值运算符2.8 BETWEEN AND运算符2.9 IN运算符2.10 NOT IN运算符2.11 LIKE运…

k8s中kubectl命令式对象、命令式对象配置、声明式对象配置管理资源介绍

目录 一.kubernetes资源管理简介 二.三种资源管理方式优缺点比较 三.命令式对象管理介绍 1.kubectl命令语法格式 2.资源类型 &#xff08;1&#xff09;通过“kubectl api-resources”来查看所有的资源 &#xff08;2&#xff09;每列含义 &#xff08;3&#xff09;常…

Java 设计模式——命令模式

目录 1.概述2.结构3.案例实现3.1.命令接口3.2.具体命令3.3.接受者3.4.调用者3.5.测试 4.优缺点5.使用场景6.JDK 源码解析——Runnable 1.概述 &#xff08;1&#xff09;日常生活中&#xff0c;我们出去吃饭都会遇到下面的场景&#xff1a; &#xff08;2&#xff09;命令模…

Go语言集成开发环境(IDE):GoLand 2023中文

GoLand 2023是一款由JetBrains开发的现代化、功能丰富的Go语言集成开发环境&#xff08;IDE&#xff09;。它提供了智能代码提示和自动完成、强大的内置调试器以及代码重构工具&#xff0c;帮助开发者提高编码效率并确保代码质量。GoLand 2023还支持多种版本控制系统&#xff0…

kubernetes-ingress-nginx

目录 一、部署 二、访问 1.基于路径访问 2.基于域名访问 三、加密与认证 1.TLS加密 2.auth认证 四、rewrite重定向 五、canary金丝雀发布 1.基于header灰度 2.基于权重灰度 3.业务域拆分 一、部署 ingress-nginx是一个开源的Kubernetes Ingress控制器&#xff0c;用…

真实经历分享:性能测试需求分析详解

在实际的工作中系统的性能需求通常是一个笼统的需求&#xff0c;而且有可能给提需求的人并不知道具体的性能需要&#xff0c;所以只能含糊的列出。如果测试人员不搞清楚&#xff0c;就会出现实际要把杀猪刀&#xff0c;需求标明能屠龙&#xff01;&#xff01;&#xff01; 下面…

C++二叉搜索树模拟实现

目录 一、二叉搜索树的概念 二、二叉搜索树的结构 三、二叉搜索树的操作&#xff08;非递归&#xff09; 1.插入 2.查找 3.删除 4.遍历 四、二叉搜索树的操作&#xff08;递归&#xff09; 1.递归插入 2.递归查找 3.递归删除 4.递归遍历 五、二叉搜索树的默认成员函…

C++ Qt QLineEdit如何响应回车事件

在Qt开发中,回车键的处理很常见,本篇博客介绍在QLineEdit里回车键的处理方法,例如下面的界面: QLineEdit回车键的处理有方式,一是链接returnPressed信号,二是用事件过滤。下面分别介绍这两种方式。 一、returnPressed信号 可以查看QLineEdit的头文件声明,有如下信号:…

python3 阿里云api进行巡检发送邮件

python3 脚本爬取阿里云进行巡检 不确定pip能不能安装上&#xff0c;使用时候可以百度一下&#xff0c;脚本是可以使用的&#xff0c;没有问题的 太长时间了&#xff0c;pip安装依赖忘记那些了&#xff0c;使用科大星火询问了下&#xff0c;给了下面的&#xff0c;看看能不能使…

成集云 | 钉钉集成用友T费用报销付款接口 |解决方案

源系统成集云目标系统 方案介绍 钉钉是一款免费沟通和协同的多端平台&#xff0c;提供PC版、Web版和手机版&#xff0c;支持手机和电脑间文件互传。钉钉帮助中国企业通过系统化的解决方案&#xff08;微应用&#xff09;&#xff0c;提升中国企业的沟通和协同效率。应用场景包…

VMware Workstation 17安装教程之设置系统模式

接上文&#xff0c;设置系统模式 返回到安装概要界面后&#xff0c;右侧第一个Installation Destination指的是想把系统安装到哪个硬盘。此时仅仅是让我们进行确认&#xff0c;不需要进行任何修改。 设置系统安装设备 关闭kdump服务 配置网络信息 当在虚拟机中做实验的时候&…

报文的路由过程

路由转发过程 记住路由转发过程结论&#xff1a;报文ip是不变&#xff0c;mac改变。 mac地址在同一个广播域传输过程中是不变的&#xff1b;在跨越广播域的时候会发生改变的&#xff1b;而IP地址在传输过程中是不会改变的&#xff08;除NAT的时候&#xff09;。 ip地址本质上是…

解析mfc100u.dll文件丢失的修复方法,快速解决mfc100u.dll问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中最常见的就是“缺少某个文件”的错误。最近&#xff0c;我也遇到了一个这样的问题&#xff0c;那就是“mfc100u.dll丢失”。这个问题可能会导致某些应用程序无法正常运行&#xff0c;给我们带来困扰。…

怎样解决“缺失msvcp110.dll”错误,msvcp110.dll的修复教程

在计算机使用过程中&#xff0c;我们可能会遇到一些系统错误提示&#xff0c;比如“msvcp110.dll文件丢失”。这是因为msvcp110.dll是Microsoft Visual C 2012的一个动态链接库文件&#xff0c;如果这个文件丢失或者损坏&#xff0c;就可能导致某些程序无法正常运行。那么&…

一种FSK信号符号同步的思想

FSK原理 FSK利用频率传输信息,即将信息流调制到频率上。以最简单的2FSK通俗来讲,用2个不同的频率 f 1 f_1 f1

淘宝协议最新版

我可以为您提供一些示例代码&#xff0c;以演示一些与电商平台相关的功能。请注意&#xff0c;以下代码仅为示例&#xff0c;具体实现还需要根据您的应用程序的架构、技术栈和需求进行调整和扩展。 1. 用户注册功能&#xff1a; - 后端实现&#xff1a;在后端&#xff0c;您可…

浅谈OSG的默认视点方向

目录 1. 前言 2. OPenGL坐标系和OSG坐标系 3. 默认视点有关的几个案例 4. 视点操作 4.1. 视点调整 4.2. 左右转动 4.3. 向前走 5. 总结 6. 参考资料 1. 前言 在OSG开发中&#xff0c;对视点的理解透彻是必须可少的&#xff0c;特别是在进行自定义操控器类的开发中&…

【组件】身份证卡片

效果展示 组件代码 <div class"cardOneRoot"><img :src"itemInfo.psnPicUrl ? itemInfo.psnPicUrl : " alt""/><div class"infoDiv" v-if"itemInfo.noInfo 1"><div v-for"(item2, index2) in …

“第五十七天”

不出意外的话&#xff0c;机组这周也就过完了&#xff0c;不过就真的是简单过一遍&#xff0c;先简单有个印象吧&#xff0c;这样看的话还是放假之前还是有机会把四大件都过一遍的。 这个思路&#xff0c;真的太神了&#xff0c;当然也是自己太弱了&#xff0c;就这我还为自己想…

VulnHub DC-3

一、信息收集 1.nmap扫描 只开放了80端口&#xff0c;所以只能从80入手 访问web页面 提示&#xff1a;只有一个flag&#xff0c;并且只有一个入口 wappalyzer插件 知道站点使用Joomla框架 使用该框架扫描工具 2.Joomla工具 joomscan --help joomscan -u 192.168.103.192 -e…