Web Worker

一. 简述:

         JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。随着电脑计算能力的增强,尤其是多核 CPU 的出现,单线程带来很大的不便,无法充分发挥计算机的计算能力。
         Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
         Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

Web Worker 有以下几个使用注意点。
  1. 同源限制:
    分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
  2. DOM 限制:
    Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window这些对象。但是,Worker 线程可以使用navigator对象和location对象。
  3. 通信联系:
    Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
  4. 脚本限制:
    Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
  5. 文件限制:
    Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

二. web work 的使用

1. 如何创建 Web Worker?

         创建一个新的 worker 十分简单。你所要做的就是调用 Worker() 构造函数,指定一个要在 worker 线程内运行的脚本的 URI,如果你希望能够与worker进行通信,接收其传递回来的数据,可以将worker的onmessage属性设置成一个特定的事件处理函数,当 web worker 传递消息时,会执行事件监听器中的代码。event.data 中存有来自 worker 的数据。。

example.html: (主页面):

var myWorker = new Worker("worker_demo.js");

myWorker.onmessage = function (event) {
  console.log("Called back by the worker!\n");
};

或者,也可以使用 addEventListener()添加事件监听器:

var myWorker = new Worker("worker_demo.js");

myWorker.addEventListener("message", function (event) {
  console.log("Worker said : " + event.data);
}, false);

myWorker.postMessage("hello my worker"); // start the worker.

         例子中的第一行创建了一个新的 worker 线程。第三行为 worker 设置了 message 事件的监听函数。当 worker 调用自己的 postMessage() 函数时就会向后台Worker发送数据,并且后台返回消息调用message这个事件处理函数。

2. 终止 web worker

         如果你想立即终止一个运行中的 worker,可以调用 worker 的terminate()方法。被终止的Worker对象不能被重启或重用,我们只能新建另一个Worker实例来执行新的任务。

myWorker.terminate();

三. 简单demo演示

下面给出一个简单的web worker例子来验证一下子线程的执行是否对页面有影响:

index.html代码:

<!DOCTYPE html>
<html>
<body>
<p>Count numbers:
    <output id="result"></output>
</p>
<button onclick="startWorker()">Start Worker</button>
<button onclick="stopWorker()">Stop Worker</button>
<input type="text" value=""/>
<script>
    var w;

    function startWorker() {
        if (typeof(Worker) !== "undefined") {
            if (typeof(w) === "undefined") {
                w = new Worker("demo_workers.js");
            }
            w.onmessage = function (event) {
                document.getElementById("result").innerHTML = event.data;
            };
        } else {
            document.getElementById("result").innerHTML = "Sorry, your browser does not support Web Workers...";
        }
    }

    function stopWorker() {
        w.terminate();
    }
</script>
</body>
</html>

demo_workers.js代码:

function timedCount () {
    for (var i = 0; i < 10000000000; i++) {
        if (i % 100000 === 0) {
            postMessage(i);
        }
    }
}

timedCount();

点击Start Worker按钮启动web worker,可以看到web worker开始工作,且在web worker正常工作时,我们仍然可以在input输入框中输入信息,这表示页面并没有因为web worker的运行而被阻塞:
在这里插入图片描述

         另外要注意一点,web worker虽然是新启动的子线程,运行不会阻塞页面,但与主线程的交互会。以上面的代码为例,如果在web worker的for循环里面直接调用postMessage,仍然会感到页面的操作不够流畅(原因是主线程需要一直不停地处理子线程post过来的消息)。

web worker的介绍至此结束,接下来聊一聊web worker的应用场景。

四. web work 的应用场景

目前可以百度到的关于web worker的文章内容大部分都是从MDN复制过来的,极少有介绍在实际项目中是如何使用web worker的,当然,按笔者的理解有两方面的原因:

  1. web worker的兼容性问题,主流浏览器对web worker的兼容性还不够高(比如Safari ,IE就更不用说了);
  2. 在项目中引入web worker并不能带来质的改变(从这一点来说,websocket就不一样,引入websocker后基本可以替换掉项目里所有的轮询,达到性能优化的目的,但正常的项目决不可能设计成让前台来处理复杂的业务逻辑)。

当然,这也不表示web worker毫无用武之地,比如下面几个场景:

大数据的处理:

         这里所说的大数据处理,并不是指数据量非常大,而是要从计算量来看,通常用时不能控制在毫秒级内的运算都可以考虑放在web worker中执行。

高频的用户交互:

         高频的用户交互适用于根据用户的输入习惯、历史记录以及缓存等信息来协助用户完成输入的纠错、校正功能等类似场景,用户频繁输入的响应处理同样可以考虑放在web worker中执行。

最后声明一点,了解后台的同学千万不要认为web worker等同于后台意义的多线程,web worker现在有了多线程的形(有了多线程的用法),但还不具备多线程的神(不具备线程通信、锁等后台线程的基本特性),web worker的本质是支持我们把数据刷新与页面渲染两个动作拆开执行(不使用web worker的话这两个动作在主线程中是线性执行的)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

. . . . .

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

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

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

打赏作者

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

抵扣说明:

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

余额充值