HTML5 Web Workers

最后更新:
阅读次数:

随着 Web 应用复杂性的日益剧增,越来越复杂耗时的计算在所难免。如果这种复杂耗时的计算直接在页面上进行计算,很容易造成浏览器或页面卡顿(JavaScript 的单线程),用户体验很不好。那么问题来了,如何处理这些复杂耗时的计算呢?

要不我们把它们拿出来异步进行处理吧!

正解, Web Workers 就是这样干的:将复杂耗时的计算从页面中抽出来,异步对它们进行处理。 这样就避免了阻塞用户界面。

浏览器实现 Web Workers 规范的方式有很多种,可以使用线程、后台进程或者运行在其他处理器核心上的进程,等等。 具体的实现细节我们接没必要深入了解了,反正 Web Workers 很有用。

Worker 对象

  • 新建一个 Worker 对象:new Worker(scriptURL)

    • 注意:脚本的路径必须遵循同源策略
  • 事件

    • message: 每当接收到消息时触发
    • error: 执行代码发生错误时触发
      • event.message: 一个可读性良好的错误信息
      • event.filename:产生错误的脚本文件名
      • event.lineno:发生错误时所在的脚本文件行号
  • 方法

    • postMessage(message[,transferList]): 传递消息
      • 这里的 message 不再仅仅是字符串,还可以是一个对象
    • terminate(): 立即终止 worker

Worker 全局作用域

  • 关于 Web Worker,最重要的是要知道它所执行的 JavaScript 代码完全是在另一个作用域中,与当前网页中的代码不共享作用域。
  • Web Worker 的内部代码不能访问 DOM,也无法通过任何方式影响页面外观
  • 在 Web Worker 中,同样有一个全局对象,这个全局对象就是页面中定义的 worker 对象本身
  • 为了便于处理数据,Web Worker 本身也是一个最小化的运行环境(WorkerGlobalScope),类似于 window 对象,它也有自己的子对象,比如:

  • WorkerGlobalScope.importScripts(‘script1.js’,’script2.js’…): 向 Worker 内部作用域引入脚本,引入的脚本的作用域也是在 Worker 的全局作用域里,并且按引入顺序依次执行

通信方式

  • Worker 是通过 message 和 error 事件与页面进行通信的,传递消息就是页面与 Worker 相互之间通信的方式。

web worker

实例解析

/*********************页面脚本*******************************/

// 新建 worker 对象
var worker = new Worker("worker.js");

// 设置 message 事件监听程序
worker.onmessage = function(event) {
console.log(event.data);
};

// 设置 error 事件监听程序
worker.onerror = function(event) {
console.log(
`ERROR---Page: ${event.filename} (${event.lineno}) ${event.message}`
);
};

// 点击页面向 worker发送消息
document.body.onclick = function() {
worker.postMessage("Hello Worker~");
};

/*********************** worker 内部脚本 **********************/

// 内部脚本即上面引入的 worker.js 文件内容

// 监听 message 事件
self.onmessage = function(event) {
// 处理数据
var data = event.data;
data = data
.split("")
.reverse()
.join("");

// 将数据发送回原页面
self.postMessage(data);
};

// 监听 error 事件
self.onerror = function(event) {
console.log(
`ERROR---Worker: ${event.filename} (${event.lineno}) ${event.message}`
);
};