解决JavaScript单线程问题——webWorkers

参考文档 使用 Web Workers - Web API 接口参考 | MDN (mozilla.org)

MDN的介绍为:

Web Worker 为 Web 内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。此外,它们可以使用 XMLHttpRequest(尽管 responseXMLchannel 属性总是为空)或 fetch(没有这些限制)执行 I/O。一旦创建,一个 worker 可以将消息发送到创建它的 JavaScript 代码,通过将消息发布到该代码指定的事件处理器(反之亦然)。

简单来说就是, 我们可以通过使用worker为主线程分担数据处理压力.

假如说你有一段很大的数据需要处理, 而你又不想这段程序阻碍你的其他操作,这时候就可以考虑一下webWorker.

如何使用webWorker

创建worker

  1. 先创建一个worker.js文件, 该文件为线程代码文件, 文件中的代码会在后台线程中运行.

  2. 在主线程中创建一个worker, 通过类似通讯的方式在主线程和worker中进行数据传递.

    // index.js主线程代码块
    // 简单创建一个worker名为myworker
    let myworker = new Worker("./firstworker.js") // 参数为firstworker.js文件的路径

主线程和worker之间进行通讯

  1. 主线程发送数据给worker: 在主线程中通过 worker.prototype.postMessage() 进行通信

    // index.js主线程代码块
    // ... 创建完worker console.log("主线程我说句话先,接下来你要替我干活了.");
    // 简单向worker中发送一个数组[1, 2, 3]
    myworker.postMessage([1, 2, 3]);
  2. worker接收来自主线程的数据: 在myworker.js中接收数据

    // firstworker.js代码块
    // 接收来自主线程的数据,数组[1, 2, 3]
    onmessage = function recive(msg) {
    // 接收到的是一个MessageEvent对象, 我们可以获取data属性
    console.log(msg.data); // 输出[1, 2, 3]
    };

    我们也可以使用更简洁的方式

    // firstworker.js代码块
    // 使用解构和匿名箭头函数
    onmessage = ({ data }) => {
    console.log(data); // 输出[1, 2, 3]
    };
  3. worker发送数据给主线程: 通过 postMessage() 发送数据给主线程 index.js

    接收到数组[1, 2, 3]之后, 我们可以简单的对数组进行一个逆序操作, 再把结果返回主线程

    // firstworker.js代码块
    onmessage = ({ data }) => {
    // 主线程发来的数据
    console.log("主线程发来的数据:", data);
    // 赋值一个新变量newdata
    let newdata = data;
    // 对新变量操作(数组逆序)
    newdata.sort((a, b) => {
    return b - a;
    });
    console.log("worker后台线程处理完成的数据newdata:", newdata);
    // 处理完的结果递交给主线程
    postMessage(newdata);
    };
  4. 主线程接收worker讯息: 通过 addEventListener() 对worker的动作进行监听

    // index.js主线程代码块
    // 主线程通过 监听 实例的message事件获取worker的数据
    // 接收myworker处理之后的结果
    myworker.addEventListener("message", ({ data }) => {
    console.log("接收到来自worker处理完的数据:", data);
    });

关闭线程

worker.terminate()可以帮助我们在主线程中随意关闭线程, 即为从主线程中立刻终止一个运行中的 worker

// index.js主线程代码块
// 3s后关闭线程
setTimeout(() => {
console.log("关闭myworker,你别说话了")
myWorker.terminate();
}, 3000); // firstworker.js代码块
setTimeout(() => {
console.log("4秒时让我说句话")
}, 4000);

worker监听

主线程通过 addEventListener() 对worker动作进行监听, 动作包含三种

  • message
  • error
  • messageError:

注意事项

  1. worker是HTML5规范的API,所以你没法在node环境中使用.
  2. worker没办法对dom元素操作, 只能在主线程中, 多线程操作dom感觉就不大好.
  3. worker可以用于执行长时间运行的计算、处理大量数据、执行网络请求等任务,而不会影响用户界面的响应性能.帮助开发人员提高Web应用程序的性能和响应性能.
  4. 本文章只对worker的使用进行了简单介绍, 具体进阶用法等详细内容还得参考MDN文档(共享worker, 线程安全, 嵌入式worker等)

JavaScript如何解决单线程缺陷——webWorker的更多相关文章

  1. JavaScript之JS单线程|事件循环|事件队列|执行栈

    本博文基于知乎"JavaScript作用域问题?"一问,而引起了对JavaScript事件循环和单线程等概念与实践上的研究.深入理解. 一.概念 0.关键词:JavaScript单 ...

  2. Javascript引擎的单线程机制和setTimeout执行原理阐述

    工作中使用setTimeout解决了一个问题,于是对setTimeout的相关资料整理了下,以及对js引擎执行的原理一并整理了下,希望能给码农们一些帮助.若发现有错的地方大家及时指出,共同学习进步. ...

  3. JavaScript到底是不是单线程

    JavaScript到底是不是单线程 JavaScript引擎 在了解计时器内部运作前,我们必须清楚一点,触发和执行并不是同一概念,计时器的回调函数一定会在指定delay的时间后被触发,但并不一定立即 ...

  4. Javascript定时器(一)——单线程

    一.JavaScript 引擎是单线程的 可以从下面的代码中看到,第一个用setTimeout中的代码是死循环,由于是单线程,下面的两个定时器就没机会执行了. <script type=&quo ...

  5. JavaScript 闭包解决计数器问题

    JavaScript 闭包解决计数器问题 var add = (function () { var counter = 0; return function () {return counter += ...

  6. JavaScript引擎是单线程的

    从基础的层面来讲,理解JavaScript的定时器是如何工作的是非常重要的.计时器的执行常常和我们的直观想象不同,那是因为JavaScript引擎是单线程的.我们先来认识一下下面三个函数是如何控制计时 ...

  7. Javascript:必须知道的Javascript知识点之“单线程事件驱动”

    heiboard: Javascript:必须知道的Javascript知识点之“单线程事件驱动”

  8. 编程原理—如何用javascript代码解决一些问题

    关于编程,我最喜欢的就是解决问题.我不相信有谁天生具有解决问题的能力.这是一种通过反复锻炼而建立并维持的能力.像任何练习一样,有一套指导方针可以帮助你更有效地提高解决问题的能力.我将介绍5个最重要的软 ...

  9. JavaScript异步和单线程

    一,同步和异步的区别: 同步会阻塞代码执行,而异步不会.(比如alert是同步,setTimeout是异步) 二,前端使用异步的场景: 1,定时任务:setTimeout,setInterval 2, ...

  10. 常见JS(JavaScript)冲突解决方法

    1.一般JS冲突解决办法 a.最容易出现的就是js的命名冲突 ①.变量名冲突 变量有全局变量和局部变量当全局变量变量和局部变量名称一致时,就会js冲突,由于变量传递数值或地址不同就会产生JavaScr ...

随机推荐

  1. ES6let const

    let const class 类 import 引入模块 export 暴露接口 // var a = 10; // let b = 20; // const c = 30; var和let比 co ...

  2. ICMP隐蔽隧道攻击分析与检测(三)

    • ICMP隧道攻击工具特征分析 一.原理 由于ICMP报文自身可以携带数据,而且ICMP报文是由系统内核处理的,不占用任何端口,因此具有很高的隐蔽性. 通过改变操作系统默认填充的Data,替换成自己 ...

  3. [Java SE]Unicode解码

    文由 将ASCII等其他非Unicode字符与Unicode混合的"脏的.不规范的"编码文本转为正常文本. 源码 unicodetoString(String unicodeTex ...

  4. 0001 嵌入式开发带你从小白到大佬系列之——Linux开发环境搭建—Windows-VMware-Ubuntu环境配置

    如文章标题,我们安装的Linux开发环境是:Windows-VMware-Ubuntu环境 配置,即在windows系统下安装VMware虚拟机,之后在VMware中配置安装Linux系统的常用发行版 ...

  5. 通过 iframe 调用 天气预报&jsonp

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. TiDB Lightning导入超大型txt文件实践

    背景 TiDB 提供了很多种数据迁移的方式,但这些工具/方案普遍对MySQL比较友好,一旦涉及到异构数据迁移,就不得不另寻出路,借助各种开源或商业的数据同步工具.其实数据在不同系统的流转当中,有一种格 ...

  7. Caused by: java.net.BindException: Address already in use: JVM_Bind(ActiveMq已经启动)

    1.本地启动项目开启两个启动类出错. Error creating bean with name 'brokerService' defined in class path resource [com ...

  8. 如何将c#在线编辑器嵌入自己项目

    如何将c#在线编辑器嵌入自己项目 首先我们需要介绍一下这个在线编辑器,当前的在线编辑器支持c#的代码编译运行,并且无需后台服务,基于WebAssembly实现的在浏览器端去执行我们的c#代码,基于Ro ...

  9. 虚拟机中Docker下部署gitlab

    一.安装Gitlab 1.拉取镜像并启动 由于服务器的80端口可能被占用,所以这里我们改成了其他端口来启动 docker run -d -p 2443:443 -p 5678:80 -p 2222:2 ...

  10. 文心一言 VS chatgpt (13)-- 算法导论3.1 8题 3.2 1题

    八.可以扩展我们的记号到有两个参数n和m的情形,其中的n和m可以按不同速率独立地趋于无穷.对于给定的函数g(n, m),用O(g(n, m))来表示以下函数集: O(g(n, m)) = 对Ω(g(n ...