Web Worker学习笔记

JavaScript 语言采用的是单线程模型,也就是说,所有任务只能在一个线程上完成,一次只能做一件事。前面的任务没做完,后面的任务只能等着。随着电脑计算能力的增强,尤其是多核 CPU 的出现,单线程带来很大的不便,无法充分发挥计算机的计算能力。

一、简述

Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。
在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。

Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

二、注意点

Web Worker 有以下几个使用注意点:

  • 同源限制
    分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。(所谓同源是指,域名,协议,端口相同。)
  • DOM 限制
    Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
  • 通信联系
    Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
  • 脚本限制
    Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
  • 文件限制
    Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。
三、基础用法

3.1 主线程
用new命令,Worker()构造函数,创建一个Worker线程

// main.js
var myworker = new Worker('work.js');

注意work.js必须是跑在服务器下的一个文件。**(后面有教不用跑服务也可以启动worker的方法)**大家可以简单用anywhere跑起一个服务。其他关于新线程的逻辑都写在worker.js里面。

主线程-传递信息
主线程是通过myworker.postMessage()方法向子线程传递消息

myworker.postMessage('hello world')
myworker.postMessage({name: 'charming'})

worker.postMessage()方法的参数,就是主线程传给 Worker 的数据。它可以是各种数据类型,包括二进制数据。

主线程-接收信息/监听事件
主线程是通过myworker.onmessage()方法监听子线程发回来的消息

myworker.onmessage  = function (event) {
	console.log('接收到子线程的消息:' + event.data)
}

主线程-终止子线程

myworker.terminate()

3.2 子线程
子线程代码都写在work.js里面

子线程-接收消息
子线程内部通过监听message接收主线程传递过来的信息。

self.addEventListener('message', function (e) {
  self.postMessage('从主线程接收到: ' + e.data);
}, false);

子线程-代码写法
在上面代码中,self表示子线程自身。即子线程的全局对象。等同于厦门两种写法

this.addEventListener('message', function (e) {
  this.postMessage('从主线程接收到: ' + e.data);
}, false);

addEventListener('message', function (e) {
  postMessage('从主线程接收到: ' + e.data);
}, false);

当然直接用onmessage监听message事件也是可以的

onmessage = function(e) {
	postMessage('从主线程接收到: ' + e.data);
}

子线程-传递信息
一样是postMessage方法。
ps可以用对象传递数据。如{ method: 'start', data: 'now start' }来区分不同的事件。

子线程-终止子线程
self.close()用于在子线程内部关闭自身。

3.3 加载脚本
子线程内部如果要加载其他脚本,有一个专门的方法importScripts()

importScripts('script1.js');
// 该方法可以同时加载多个脚本。
importScripts('script1.js', 'script2.js');

3.4 错误处理
主线程可以监听子线程是否发生错误。如果发生错误,子线程会触发主线程的error事件。

myworker.onerror(function (event) {
  console.log([
    'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
  ].join(''));
});
// 或者
myworker.addEventListener('error', function (event) {
  // ...
});
四、新建worker不用运行在服务器上

通常情况下,子线程载入的是一个单独的 JavaScript 脚本文件,但是也可以载入与主线程在同一个网页的代码。

<!DOCTYPE html>
  <body>
    <script id="worker" type="app/worker">
      addEventListener('message', function () {
        postMessage('some message');
      }, false);
    </script>
  </body>
</html>

上面是一段嵌入网页的脚本,注意必须指定<script>标签的type属性是一个浏览器不认识的值,上例是app/worker
然后,读取这一段嵌入页面的脚本,用 Worker 来处理。

var blob = new Blob([document.querySelector('#worker').textContent]);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);

worker.onmessage = function (e) {
  // e.data === 'some message'
};
五、实际应用场景
  • 比较常见的是把计算丢给子线程,然后子线程完成之后再通知主线程更新。
  • 让子线程完成轮询。
六、参考文献

Web Worker使用教程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值