什么是Web Worker?
web worker 是运行在后台的 JavaScript,不占用浏览器自身线程,独立于其他脚本,可以提高应用的总体性能,并且提升用户体验。
一般来说Javascript和UI页面会共用一个线程,在HTML页面中执行js脚本时,页面的状态是不可响应的,直到脚本已完成。而这段代码可以交给Web Worker在后台运行,那么页面在Javascript运行期间依然可以响应用户操作。后台会启动一个worker线程来执行这段代码,用户可以创建多个worker线程。
有两种 Web WorkerWeb workers可分为两种类型:专用线程dedicated web worker,以及共享线程shared web worker。 Dedicated web worker随当前页面的关闭而结束;这意味着Dedicated web worker只能被创建它的页面访问。与之相对应的Shared web worker可以被多个页面访问。在Javascript代码中,“Work”类型代表Dedicated web worker,而“SharedWorker”类型代表Shared web worker。
在绝大多数情况下,使用Dedicated web worker就足够了,因为一般来说在web worker中运行的代码是专为当前页面服务的。而在一些特定情况下,web worker可能运行的是更为普遍性的代码,可以为多个页面服务。在这种情况下,我们会创建一个共享线程的Shared web worker,它可以被与之相关联的多个页面访问,只有当所有关联的的页面都关闭的时候,该Shared web worker才会结束。相对Dedicated web worker,shared web worker稍微复杂些。
new Worker()对象代表Dedicated Web Worker,以下示例代码都为Dedicated Web Worker。
如何创建 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这个事件处理函数。
注意: 传入 Worker 构造函数的参数 URI 必须遵循为了高效地传输 ArrayBuffer 对象数据,需要在 postMessage 方法中的第二个参数中指定它。实例代码如下:
myWorker.postMessage({ operation: 'list_all_users', //ArrayBuffer object input: buffer, threshold: 0.8, }, [buffer]);
worker_demo.js (worker):
postMessage("I\'m working before postMessage(\'hello my worker\')."); onmessage = function (event) { postMessage("Hi " + event.data); };
注意: 通常来说,后台线程 – 包括 worker – 无法操作 DOM。 如果后台线程需要修改 DOM,那么它应该将消息发送给它的创建者,让创建者来完成这些操作。
通过Web Worker你可以在前台做一些小规模分布式计算之类的工作,不过Web Worker有以下一些使用限制:
不过Web Worker作用域中依然可以使用有:
importScripts('foo.js'); importScripts('foo.js', 'bar.js');
浏览器将列出的脚本加载并运行。每个脚本中的全局对象都能够被 worker 使用。如果脚本无法加载,将抛出 NETWORK_ERROR 异常,接下来的代码也无法执行。而之前执行的代码(包括使用setTimeout延迟执行的代码)却依然能够使用。importScripts()之后的函数声明依然能够使用,因为它们始终会在其他代码之前运行。注意: 脚本的下载顺序不固定,但执行时会按照你将文件名传入到importScripts()中的顺序。这是同步完成的;直到所有脚本都下载并运行完毕,importScripts()才会返回。
下面简单写下Web Worker使用XMLHttpRequest与服务端通信: