Web Worker

Web Worker?

我们都知道JavaScript是单线程的,至于为什么是单线程的,以下内容来源阮一峰前辈的文章

作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

但这样的话,并不是很高效,因为单线程无法充分发挥计算机的计算能力。所以
为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。

在使用Web Worker前需要注意

  • Worker 的全局对象是WorkerGlobalScope,与主线程不一样,,所以其无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以使用navigator对象和location对象。
  • Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。

Web Worker 基本使用

主线程

创建线程

// 创建线程,work.js为线程的脚本文件
var worker1 = new Worker('worker1.js');

在这里插入图片描述
基本操作

// 发送消息
worker1.postMessage('Hello World');

// 接收消息
worker1.onmessage=e=>{
   console.log(e.data);
}

// 关闭线程
worker1.terminate();

Worker线程

self代表子线程自身,即子线程的全局对象。

// 接收消息 and 发送消息
//(1)
self.addEventListener('message', function (e) {
 self.postMessage(e.data);
});
//(2)
addEventListener('message', function (e) {
  postMessage( e.data);
});

// 关闭
//(1)
self.close()
//(2)
close();

Web Worker的优势在哪?

我们通过一个例子来说明多线程的优势

在没有线程的情况下,主线程运行三个斐波那契函数所需事件如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function fb(n){     
            if(n==1||n==2){
                return 1;
            }
            return fb(n-1)+fb(n-2)
        }
        console.time('三个fb执行时间');
        var result=fb(40)
        var result=fb(40)
        var result=fb(40) 
        console.timeEnd('三个fb执行时间')
    </script>
</body>
</html>

在这里插入图片描述

现在我们创建三个进程,每一个进程运行一个函数

主线程代码

 var worker1=new Worker('worker1.js');
        var worker2=new Worker('worker2.js');
        var worker3=new Worker('worker3.js');
        worker1.onmessage=e=>{
            console.log(e.data);
        }
        worker2.onmessage=e=>{
            console.log(e.data);
        }
        worker3.onmessage=e=>{
            console.log(e.data);
        }

另外三个线程代码如下

function fb(n){

    if(n==1||n==2){
        return 1;
    }
    return fb(n-1)+fb(n-2)
}
console.time('fb执行时间1');
var result=fb(40)
console.timeEnd('fb执行时间1')
self.postMessage('worker1');
function fb(n){

    if(n==1||n==2){
        return 1;
    }
    return fb(n-1)+fb(n-2)
}
console.time('fb执行时间2');
var result=fb(40)
console.timeEnd('fb执行时间2')
self.postMessage('worker2');
function fb(n){

    if(n==1||n==2){
        return 1;
    }
    return fb(n-1)+fb(n-2)
}
console.time('fb执行时间3');
var result=fb(40)
console.timeEnd('fb执行时间3')
self.postMessage('worker3');

在这里插入图片描述
从这个例子我们可以看出,如果我们没有线程,主线程执行三个函数需要9.669s的时间。而当我们创建三个线程,一个线程执行一个函数时,主线程得到结果的最长时间为2.217s

所以在实际中,我们一般使用Worker线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务可以交由 Worker 线程执行,主线程(通常负责 UI 交互)能够保持流畅,不会被阻塞或拖慢。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焦妮敲代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值