初探Web Workers

日期:2021-06-09 23:55:00

更新:2021-06-09 23:55:00

标签:前端, Javascript

分类:Javascript

Web Workers are a simple means for web content to run scripts in background threads. The worker thread can perform tasks without interfering with the user interface.

初探Web Workers

Web Workers 是什么

Web Workers are a simple means for web content to run scripts in background threads. The worker thread can perform tasks without interfering with the user interface.[1]

简单的翻译就是:Web Workers是一个关于在 web 内容中跑脚本的后台线程的简单方法。工作线程可以在不干扰用户界面的同时执行任务。

看完上面的描述后,可以了解到,他可以在 Web 页面中创建线程(或进程,不同浏览器中的 Worker 实现不一样)去执行主程序之外的其他任务。

使用 WebWorker

要使用 webWorker 很简单,首先创建一个worker实例

new Worker(URL, options);
/**
 * 它接受两个参数,分别是:
 * URL 表示worker 将执行的脚本的URL。它必须遵守同源策略
 * options {
 *   type: 'classic' | 'module', // 用以指定 worker 类型的  DOMString 值.
 *   credentials: 'omit' | 'same-origin' | 'include', // 用以指定 worker 凭证的 DOMString 值
 *   name: string, // 在 DedicatedWorkerGlobalScope 的情况下,用来表示 worker 的 scope 的一个 DOMString 值,主要用于调试目的
 * }
 */

webworker 实例提供两个监听器:onmessageonerror。同时他还提供postMessage方法
onmessage就是监听到数据传入时触发的方法,onerror则是用于错误捕捉.
postMessage用于传输数据到工作线程。 通过这些监听器和方法,可以了解到 worker 的工作流程如下图。

根据时序图可以编写出程序:

// main.js
const worker = new Worker("worker.js");
worker.postMessage("hello");

worker.onmessage = function (e) {
  console.log(e.data); // Result: hello
  worker.terminate();
};
worker.terminate();
// worker.js
self.onmessage = function (e) {
  console.log(e.data); // hello
  var workerResult = "Result: " + e.data;
  postMessage(workerResult);
};

上述代码就是一个简单的 worker 工作流程。
主线程创建 worker 后,加载 worker.js,worker.js 必须与主页面同源的!!,之后 worker 向线程发送消息。
worker.js 收到消息后,执行应的代码,再执行window.PostMessage将数据返回到主页面中。
主页面收到信息后触发 onmessage 方法,最后调用terminate结束工作线程。
自此,主页面与工作线程通信结束

Worker 的全局作用域

可以注意到,worker是一个 JS 脚本文件那么可以知道,他的作用域与主页面是独立的,也就是他们不共享作用与,所以 web worker 是无法改变 DOM 的。可以看到,worker 线程与主页面相比功能是有限的。
worker 中的全局提供的全局方法有[2]:

  1. 最小化的 navigator 对象,包括 onLine,appName,appVersion,userAgent,platform 属性
  2. 提供只读的 location
  3. 提供 setTimeout,setInterval,clearTimeout,clearInterval 方法
  4. 提供 XMLHttpRequest

除此之外 worker 中还能引入其他的脚本文件,我们可以调用importScript()的方法接受一个或多个脚本文件。又是需要注意,引入的脚本不能使用包含页面操作的代码。

共享 Worker

上面介绍的 worker 是只能被生成它的父页面所调用,他是被一个主页面所独占的,这样的 worker 就叫做专用worker
除了专用 worker,还有一种工作线程可以被多个主页面所调用,这种 worker 就叫做共享 Worker
window 提供shareWorker类来创建共享 Worker

// 传入的参数与专用worker一致
const share = new ShareWorker(URL, options);
/**
 * share返回一个port属性
 * share.port
 * share.port.start() 开放传输的端口
 * share.port.end() 关闭传输的端口
 * share.port.postMessage() 发送消息,必须先调用share.port.start方法
 */

了解了共享 Worker 后,我们再来写一个例子

// main_1.js 主页面 1
const share = new ShareWorker("worker.js");
share.port.start();
share.port.postMessage("hello");
// 接收消息出发
share.port.onmessage = function (e) {
  console.log(e.data); // Result: hello
};

// worker.js
onconnect = function (e) {
  const main_1 = e.port[0];
  main_1.onmessage = function (e) {
    main_1.postMessage(`Result: ${e.data}`);
  };
};

小结

本文主要介绍了 web workers 的概念和作用。

若您觉得文章对你有帮助,可以点一个赞鼓励一下作者,若想了解更多 JavaScript 或者 node 知识可以点击这里

参考

  1. Web Workers
  2. JavaScript 高级程序设计