前端 Web Workers 简介

news2024/11/26 20:22:42

简介

以前我们总说,JS 是单线程没有多线程,当 JS 在页面中运行长耗时同步任务的时候就会导致页面假死影响用户体验,从而需要设置把任务放在任务队列中;执行任务队列中的任务也并非多线程进行的,然而现在 HTML5 提供了我们前端开发这样的能力 - Web Workers API,我们一起来看一看 Web Worker 是什么,怎么去使用它,在实际生产中如何去用它来进行产出。

概述

Web Workers 使得一个 Web 应用程序可以在与主执行线程分离的后台线程中运行一个脚本操作。这样做的好处是可以在一个单独的线程中执行费时的处理任务,从而允许主(通常是 UI)线程运行而不被阻塞。

它的作用就是给 JS 创造多线程运行环境,允许主线程创建 worker 线程,分配任务给后者,主线程运行的同时 worker 线程也在运行,相互不干扰,在 worker 线程运行结束后把结果返回给主线程。这样做的好处是主线程可以把计算密集型或高延迟的任务交给 worker 线程执行,这样主线程就会变得轻松,不会被阻塞或拖慢。这并不意味着 JS 语言本身支持了多线程能力,而是浏览器作为宿主环境提供了 JS 一个多线程运行的环境。

不过因为 worker 一旦新建,就会一直运行,不会被主线程的活动打断,这样有利于随时响应主线程的通性,但是也会造成资源的浪费,所以不应过度使用,用完注意关闭。或者说:如果 worker 无实例引用,该 worker 空闲后立即会被关闭;如果 worker 实列引用不为 0,该 worker 空闲也不会被关闭。

兼容性

在这里插入图片描述

注意事项

worker 线程的使用有一些注意点:

  1. 同源限制 worker 线程执行的脚本文件必须和主线程的脚本文件同源,这是当然的了,总不能允许 worker 线程到别人电脑上到处读文件吧
  2. 文件限制 为了安全,worker 线程无法读取本地文件,它所加载的脚本必须来自网络,且需要与主线程的脚本同源
  3. DOM 操作限制 worker 线程在与主线程的 window 不同的另一个全局上下文中运行,其中无法读取主线程所在网页的 DOM 对象,也不能获取 document、window等对象,但是可以获取navigator、location(只读)、XMLHttpRequest、setTimeout族等浏览器API
  4. 通信限制 worker 线程与主线程不在同一个上下文,不能直接通信,需要通过postMessage方法来通信
    脚本限制 worker 线程不能执行alert、confirm,但可以使用 XMLHttpRequest 对象发出 ajax 请求

示例

在主线程中生成 Worker 线程很容易:

var myWorker = new Worker(jsUrl, options)

Worker() 构造函数,第一个参数是脚本的网址(必须遵守同源政策),该参数是必需的,且只能加载 JS 脚本,否则报错。第二个参数是配置对象,该对象可选。它的一个作用就是指定 Worker 的名称,用来区分多个 Worker 线程。

// 主线程

var myWorker = new Worker('worker.js', { name : 'myWorker' });

// Worker 线程
self.name // myWorker

关于 api 什么的,直接上例子大概就能明白了,首先是 worker 线程的 js 文件:

workerThread1.js 文件中

关于 api 什么的,直接上例子大概就能明白了,首先是 worker 线程的 js 文件:

// workerThread1.js

let i = 1

function simpleCount() {
  i++
  self.postMessage(i)
  setTimeout(simpleCount, 1000)
}

simpleCount()

self.onmessage = ev => {
  postMessage(ev.data + ' 呵呵~')
}

在 HTML 文件中的 body 中:

HTML 文件中的 body 中:

<!--主线程,HTML文件的body标签中-->

<div>
  Worker 输出内容:<span id='app'></span>
  <input type='text' title='' id='msg'>
  <button onclick='sendMessage()'>发送</button>
  <button onclick='stopWorker()'>stop!</button>
</div>

<script type='text/javascript'>
  if (typeof(Worker) === 'undefined')	// 使用Worker前检查一下浏览器是否支持
    document.writeln(' Sorry! No Web Worker support.. ')
  else {
    window.w = new Worker('workerThread1.js')
    window.w.onmessage = ev => {
      document.getElementById('app').innerHTML = ev.data
    }
    
    window.w.onerror = err => {
      w.terminate()
      console.log(error.filename, error.lineno, error.message) // 发生错误的文件名、行号、错误内容
    }
    
    function sendMessage() {
      const msg = document.getElementById('msg')
      window.w.postMessage(msg.value)
    }
    
    function stopWorker() {
      window.w.terminate()
    }
  }
</script>

api

主线程中的api,worker表示是 Worker 的实例:

  • worker.postMessage: 主线程往 worker 线程发消息,消息可以是任意类型数据,包括二进制数据
  • worker.terminate: 主线程关闭 worker 线程
  • worker.onmessage: 指定 worker 线程发消息时的回调,也可以通过worker.addEventListener(‘message’,cb)的方式
  • worker.onerror: 指定 worker 线程发生错误时的回调,也可以 worker.addEventListener(‘error’,cb)

Worker 线程中全局对象为 self,代表子线程自身,这时 this指向self,其上有一些 api:

  • self.postMessage: worker 线程往主线程发消息,消息可以是任意类型数据,包括二进制数据
  • self.close: worker 线程关闭自己
  • self.onmessage: 指定主线程发 worker 线程消息时的回调,也可以self.addEventListener(‘message’,cb)
  • self.onerror: 指定 worker 线程发生错误时的回调,也可以 self.addEventListener(‘error’,cb)

注意,w.postMessage(aMessage, transferList) 方法接受两个参数,aMessage 是可以传递任何类型数据的,包括对象,这种通信是拷贝关系,即是传值而不是传址,Worker 对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给 Worker,后者再将它还原。一个可选的 Transferable 对象的数组,用于传递所有权。如果一个对象的所有权被转移,在发送它的上下文中将变为不可用(中止),并且只有在它被发送到的 worker 中可用。可转移对象是如 ArrayBuffer,MessagePort 或 ImageBitmap 的实例对象,transferList数组中不可传入 null。

worker 线程中加载脚本的 api:

importScripts('script1.js')	// 加载单个脚本
importScripts('script1.js', 'script2.js')	// 加载多个脚本

使用场景

个人觉得,Web Worker 我们可以当做计算器来用,需要用的时候掏出来摁一摁,不用的时候一定要收起来。

加密数据 有些加解密的算法比较复杂,或者在加解密很多数据的时候,这会非常耗费计算资源,导致 UI 线程无响应,因此这是使用 Web Worker 的好时机,使用 Worker 线程可以让用户更加无缝的操作 UI。

预取数据 有时候为了提升数据加载速度,可以提前使用 Worker 线程获取数据,因为 Worker 线程是可以是用 XMLHttpRequest 的。

预渲染 在某些渲染场景下,比如渲染复杂的 canvas 的时候需要计算的效果比如反射、折射、光影、材料等,这些计算的逻辑可以使用 Worker 线程来执行,也可以使用多个 Worker 线。

复杂数据处理场景 某些检索、排序、过滤、分析会非常耗费时间,这时可以使用 Web Worker 来进行,不占用主线程。

预加载图片 有时候一个页面有很多图片,或者有几个很大的图片的时候,如果业务限制不考虑懒加载,也可以使用 Web Worker 来加载图片,可以参考一下这篇文章的探索这篇文章的探索,这里简单提要一下。

// 主线程
let w = new Worker("js/workers.js");
w.onmessage = function (event) {
  var img = document.createElement("img");
  img.src = window.URL.createObjectURL(event.data);
  document.querySelector('#result').appendChild(img)
}

// worker线程
let arr = [...好多图片路径];
for (let i = 0, len = arr.length; i < len; i++) {
    let req = new XMLHttpRequest();
    req.open('GET', arr[i], true);
    req.responseType = "blob";
    req.setRequestHeader("client_type", "DESKTOP_WEB");
    req.onreadystatechange = () => {
      if (req.readyState == 4) {
      postMessage(req.response);
    }
  }
  req.send(null);
}

在实战的时候注意

  1. 虽然使用 worker 线程不会占用主线程,但是启动 worker 会比较耗费资源
  2. 主线程中使用 XMLHttpRequest 在请求过程中浏览器另开了一个异步 http 请求线程,但是交互过程中还是要消耗主线程资源

在 Webpack 项目里面使用 Web Worker 请参照:怎么在 ES6+Webpack 下使用 Web Worker

参考文章

mdn

前端 Web Workers 到底是什么

Web Worker在项目中的妙用

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

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

相关文章

如何一个例子玩明白GIT

一个例子玩明白GIT GIT的介绍和教程五花八门&#xff0c;但实际需要用的就是建仓、推送、拉取等操作&#xff0c;这儿咱可以通过一个例子熟悉这些操作&#xff0c;一次性搞定GIT的使用方法学习。下面这个例子的内容是内容是建立初始版本库&#xff0c;然后将数据复制到 "远…

05-详解Nacos配置管理中心,配置拉取的方式,热更新,配置共享(优先级)的步骤

Nacos配置管理 新建配置文件 当微服务部署的实例越来越多时,如果需要修改微服务的配置就需要逐个修改配置文件并且还要重启关联的微服务十分繁琐还易出错 项目中的配置文件分为每个项目特有的配置,项目所公用的配置 每个项目特有的配置: 有些项目中需要但有些项目中又不需要…

初学者如何入门 Generative AI 之 Stable Diffusion 与 CLIP :看两篇综述,玩几个应用感受一下先!超多高清大图,沉浸式体验

文章大纲 4种 图片生成 的算法扩散模型的起源Stable DiffusionCLIP参考文献与学习路径A synthography of an astronaut riding a horse created in NightCafe Studio with Stable Diffusion XL (SDXL). Prompt is a photograph of an astronaut riding a horse with weight of …

lenovo联想拯救者Legion R7000P 2020H(82GR)笔记本原厂Windows10系统包

拯救者笔记本电脑原装出厂WIN10系统ISO镜像 链接&#xff1a;https://pan.baidu.com/s/1iPNXELRipKaAIR-yaq5HNg?pwdm27n 提取码&#xff1a;m27n 自带有所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;1…

【网络奇缘系列】计算机网络|数据通信方式|数据传输方式

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏: 一见倾心,再见倾城 --- 计算机网络~&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 这篇文章是关于计算机网络中数据通信的基础知识点&#xff0c; 从模型&#xff0c;术语再到数据通信方式&#…

Jmeter 请求签名api接口-BeanShell

Jmeter 请求签名api接口-BeanShell 项目签名说明编译扩展jar包jmeter 使用 BeanShell 调用jar包中的签名方法 项目签名说明 有签名算法的api接口本地不好测试&#xff0c;使用BeanShell 扩展jar 包对参数进行签名&#xff0c;接口签名算法使用 sha512Hex 算法。签名的说明如下…

java实现网络聊天

网络聊天实现步骤&#xff08;从功能谈论方法&#xff09;&#xff1a; 客户端&#xff1a; 1.登录面板&#xff1a;注册提醒用户注册格式&#xff0c;登录账号密码不为空&#xff0c;点击登录的时候需要连接服务器端&#xff0c;启动聊天面板。&#xff08;监听用户点击登录…

详细介绍开源固件-TF-A

什么是TF-A&#xff1f; TF-A&#xff08;Trusted Firmware-A&#xff09;是一种用于嵌入式系统的开源固件&#xff0c;而不是Linux的一部分。TF-A主要用于ARM架构的处理器和设备&#xff0c;它提供了一组安全和可信任的软件组件&#xff0c;用于引导和初始化系统。 如下是其…

学习通【劳动通论】2023章节练习题

社会主义核心价值观24个字是&#xff1a;富强、民主、文明、和谐&#xff0c;自由、平等、公正、法治&#xff0c;爱国、敬业、诚信、友善。 1、“富强、民主、文明、和谐”&#xff0c;是我国社会主义现代化国家的建设目标&#xff0c;也是从价值目标层面对社会主义核心价值观…

基于Java Swing泡泡龙游戏(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

uniapp iOS离线打包——运行项目到模拟器报错?

运行项目、打包时报错问题 记录个人在开发过程中遇到的相关问题&#xff0c;后续有时间会不定时更新 文章目录 运行项目、打包时报错问题运行到模拟器报错解决方案 打包报错解决方案 运行到模拟器报错 解决方案 选中项目工程 —> Build Settings 滑动底部 —> User-Defi…

3.DevEco Studio安装鸿蒙手机app本地模拟器

配合Intel CPU启动模拟器 解决措施 打开任务管理器&#xff0c;在“性能”选项&#xff0c;检查CPU虚拟化是否已经启用。如果未启用&#xff0c;需要进入电脑的BIOS中&#xff0c;将CPU的“Intel Virtualization Technology”选项开启。 点击New Emulator 文档中心 解决措施…

048:利用vue-video-player播放m3u8

第048个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

pyqt5使用Designer实现按钮上传图片

pyqt5使用Designer实现按钮上传图片 1、ui界面 2、ui转py代码 其中uploadimg.py代码如下&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from reading ui file uploadimg.ui # # Created by: PyQt5 UI code generator 5.15.4 # # WARNING: Any manua…

【小沐学Python】Python实现TTS文本转语音(speech、pyttsx3、百度AI)

文章目录 1、简介2、Windows语音2.1 简介2.2 安装2.3 代码 3、pyttsx33.1 简介3.2 安装3.3 代码 4、ggts4.1 简介4.2 安装4.3 代码 5、SAPI6、SpeechLib7、百度AI8、百度飞桨结语 1、简介 TTS(Text To Speech) 译为从文本到语音&#xff0c;TTS是人工智能AI的一个模组&#xf…

【unity实战】一个通用的FPS枪支不同武器射击控制脚本

文章目录 前言模型素材文章用到的粒子火光特效射击效果换弹瞄准开枪抖动效果设置显示文本最终代码不同武器射击效果1. 手枪2. 机枪3. 狙击枪4. 霰弹枪5. 加特林 其他感谢完结 前言 实现FPS枪支不同武器效果&#xff0c;比如手枪&#xff0c;喷子&#xff0c;狙击枪&#xff0c…

Dubbo入门直接上手,结合微服务详解

Dubbo 高性能、轻量级的 Java RPC 框架 RPC&#xff1a; Remote Procedure Call 远程过程调用&#xff0c;简单来说就是它允许一个计算机程序通过网络请求调用另一个计算机上的程序&#xff0c;就像本地调用一样。有非常多的协议和技术来都实现了RPC的过程&#xff0c;比如&a…

MySQL数据库,创建和管理表

创建数据库&#xff1a; 方式一&#xff1a;创建数据库 CREATE DATABASE 数据库名&#xff1b;&#xff08;使用的是默认的字符集&#xff09; 方式二&#xff1a;创建数据库并指定字符集 CREATE DATABASE 数据库名 CHARACTER SET 字符集&#xff1b; 方式三&#xff1a;判断数…

【原创】【一类问题的通法】【真题+李6卷6+李4卷4(+李6卷5)分析】合同矩阵A B有PTAP=B,求可逆阵P的策略

【铺垫】二次型做的变换与相应二次型矩阵的对应&#xff1a;二次型f&#xff08;x1&#xff0c;x2&#xff0c;x3&#xff09;xTAx&#xff0c;g&#xff08;y1&#xff0c;y2&#xff0c;y3&#xff09;yTBy ①若f在可逆变换xPy下化为g&#xff0c;即P为可逆阵&#xff0c;有P…

【大数据】Hudi 核心知识点详解(二)

&#x1f60a; 如果您觉得这篇文章有用 ✔️ 的话&#xff0c;请给博主一个一键三连 &#x1f680;&#x1f680;&#x1f680; 吧 &#xff08;点赞 &#x1f9e1;、关注 &#x1f49b;、收藏 &#x1f49a;&#xff09;&#xff01;&#xff01;&#xff01;您的支持 &#x…