web worker

单线程与多线程

在很长的一段时间内,JavaScript都是一门单线程语言,所以在JavaScript中任何会导致页面阻塞的操作都是异步运行的,虽然异步能最大限度的保证用户的浏览体验,但如果在同步代码中执行时间过长的话还是会导致页面假死

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button onclick="console.log('Hello World!')">log</button>
    <script>
        while (true) { }
    </script>
</body>

</html>

假死
可以看到页面没有任何东西加载出来,渲染主线程一直在执行JavaScript
虽然我们平时不会刻意的去写这种死循环,但毫无疑问的是,如果JavaScript中存在多线程的话能解决以前的很多问题

webworker

webworker是随着HTML5一起推出的一个API

Web Worker可以让Web应用程序具备后台的处理能力,它支持多线程处理功能,因此可以充分利用多核CPU带来的优势,将耗时长的任务分配给Web Worker运行,从而避免了有时页面反应迟缓,甚至假死的现象

我们使用new worker来创建一个新线程

const myWorker = new Worker("worker.js");

Worker构造器需要传入一个URI来指定js

self

和主线程不同, worker 运行在另一个全局上下文中,不同于当前的window,因此,在Worker内通过window获取全局作用域将返回错误,我们应该使用self来得到全局上下文

onmessage和postmessage

主线程与其他线程的通信统一使用onmessage和postmessage
以下是一个简单的通过Worker来实现计算器的案例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web Worker 加法计算器</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            height: 100vh;
        }

        .container {
            text-align: center;
        }

        input {
            margin: 5px;
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>Web Worker 加法计算器</h1>
        <input type="number" id="num1" placeholder="输入第一个数">
        <input type="number" id="num2" placeholder="输入第二个数">
        <button onclick="calculate()">计算</button>
        <p>结果: <span id="result"></span></p>
    </div>
    <script>
        if (window.Worker) {
            const worker = new Worker('worker.js');
            function calculate() {
                const num1 = document.getElementById('num1').value;
                const num2 = document.getElementById('num2').value;
                worker.postMessage({ num1: parseFloat(num1), num2: parseFloat(num2) });
            }
            worker.onmessage = function (event) {
                document.getElementById('result').textContent = event.data.result;
            }
        } else {
            console.log('您的浏览器不支持Web Worker.');
        }
    </script>
</body>

</html>

Worker.js

self.onmessage = function (event) {
    const { num1, num2 } = event.data;
    const result = num1 + num2;
    self.postMessage({ result });
}

结果

webworker限制

虽然webworker让JavaScript从此拥有了多线程编程的能力,但webworker也有着诸多限制

  1. 不能跨域加载 JavaScript
  2. Worker 内代码不能访问 DOM
  3. 使用 Web Worker 加载数据没有 JSONP 和 Ajax 加载数据高效

线程安全

虽然Worker接口会生成真正的操作系统级别的线程,但webworker中我们无法去访问非线程安全的组件或者是DOM,哪怕是通过postmessage在主线程与worker之间传递的数据也是通过拷贝而不是共享来完成的,这说明传递给worker的数据本质上是原数据的副本,页面与worker不会共享同一个实例

shareWorker

webworker其实分为两种类型

  1. 专用线程
    即我们上面提到的所有Worker,专用线程通过Worker来得到,只能由当前页面访问,在页面关闭时自动销毁
  2. 共享线程
    共享线程通过SharedWorker来得到,可以被多个页面访问

和专用线程不同,共享线程必须要显式的打开端口并通过port对象来进行通信,但在专用线程中这一部分是隐式的

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值