web Worker 应用

1、简介

  • Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。此外,他们可以使用[XMLHttpRequest](https://developer.mozilla.org/enUS/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIXMLHttpRequest)执行 I/O (尽管responseXMLchannel属性总是为空)。

2、作用

  • Web Workers 的基本组成:

Worker
一个新线程,在后台运行,不会阻塞任何主用户界面脚本(作为后台脚本被调用)。Workers 是相对重量级的,不要大规模使用。
一个 worker 可以执行不少任务,包括并行计算、后台 I/O、以及客户端数据库操作。worker 不应该中断主 UI 或直接操作 DOM;它应该向主线程返回一个消息,并让主线程更新主 UI。

Subworker
在一个 worker 中创建的 worker。Subworkers 必须与父页面同根同源。subworkers 的 URI 是根据父 worker 的地址而不是自己页面地址确定的。

Shared worker
一个可以被多个页面通过多个连接所使用的 worker,共享 worker 和普通 worker 的工作方式略有不同,只有一小部分浏览器支持这一特性。

3、注意事项

  • 同源限制 worker线程执行的脚本文件必须和主线程的脚本文件同源,这是当然的了,总不能允许worker线程到别人电脑上到处读文件吧
    文件限制 为了安全,worker线程无法读取本地文件,它所加载的脚本必须来自网络,且需要与主线程的脚本同源
  • DOM操作限制 worker线程在与主线程的window不同的另一个全局上下文中运行,其中无法读取主线程所在网页的DOM对象,也不能获取 document、 window等对象,但是可以获取 navigator、 location(只读)、XMLHttpRequest、 setTimeout族等浏览器API。
  • 通信限制 worker线程与主线程不在同一个上下文,不能直接通信,需要通过 postMessage方法来通信。
  • 脚本限制 worker线程不能执行 alert、 confirm,但可以使用 XMLHttpRequest 对象发出ajax请求。

4、api

  • worker.postMessage: 主线程往worker线程发消息,消息可以是任意类型数据,包括二进制数据
  • worker.terminate: 主线程关闭worker线程
  • worker.onmessage: 指定worker线程发消息时的回调,也可以通过worker.addEventListener('message',cb)的方式
  • worker.onerror: 指定worker线程发生错误时的回调,也可以worker.addEventListener('error',cb)

Worker线程中全局对象为 self,代表子线程自身,这时 this指向 self,其上有一些api:

  • self.postMessage: worker线程往主线程发消息,消息可以是任意类型数据,包括二进制数据
  • self.close: worker线程关闭自己
  • self.onmessage: 指定主线程发worker线程消息时的回调,也可以self.addEventListener('message',cb)
  • self.onerror: 指定worker线程发生错误时的回调,也可以 self.addEventListener('error',cb)
    w.postMessage(aMessage,transferList) 方法接受两个参数, aMessage 是可以传递任何类型数据的,包括对象,这种通信是拷贝关系,即是传值而不是传址,Worker 对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是,先将通信内容串行化,然后把串行化后的字符串发给 Worker,后者再将它还原。一个可选的 Transferable对象的数组,用于传递所有权。如果一个对象的所有权被转移,在发送它的上下文中将变为不可用(中止),并且只有在它被发送到的worker中可用。可转移对象是如ArrayBuffer,MessagePort或ImageBitmap的实例对象, transferList数组中不可传入null。

更详细的API参见 MDN - WorkerGlobalScope。

5、DEMO

要创建一个新 worker,您只需要调用 worker 构造函数,worker 脚本 URL 是惟一参数。worker 创建完成的同时启动一个新线程(或者可能是一个新进程,根据您浏览的实现而定)。
// 创建work线程 var work = new Worker('./Thread/work.js');
注意:Worker()构造函数的参数是一个脚本文件,该文件就是Worker线程需要执行的任务,由于Worker不能读取本地文件,所以这个脚本必须来自网络。
如果我们在本地调用 work.js 线程的话,就会报如下错

err.png

初始化完成后就可以使用 worker.postMessage()方法,向Worker线程发送消息
worker.postMessage 方法可以接受任何类型的参数,甚至包括二进制数据。
发送消息完成后,子线程去处理操作,通过self.postMessage()方法重新发送到主线程如下代码所示:



那么主线程通过 worker.onmessage 指定监听函数,接收子线程传送回来的消息


如果我们的worker线程任务完成后,可以通过worker.terminate();方法关闭线程。

你可能感兴趣的:(web Worker 应用)