WebWorker 简单使用方式

WebWorker 一定程度上可以算得上是浏览器中的多线程技术了,在项目中适当使用 Worker 来做一些耗时的操作能大大提高页面整体流畅度。

Worker的使用也是非常简单的,通过向 Worker 构造函数传递需要在worker中运行的文件路径作为参数,就可以使得对应的文件运行在worker线程。

Worker线程中没有 window 对象,也没有 document 对象。既不能操作也不能创建 DOM。而且 worker 线程和主线程只能通过消息机制来通信。

下面是一个 WebWorker 的简单用法:

首先需要创建一个 Worker 实例:

var worker = new Worker('worker.js');

在 worker.js 中写下如下代码:

1 console.log('Hello world');

然后 worker.js 就会在 worker 线程中运行,这也就意味着这里的代码不管是什么,基本上可以认为对主线程(也就是浏览器线程)没有任何影响。虽然实际上电脑跑的东西越多性能越差,但至少主线程不会被阻塞。

无法跟主线程交互的代码用处非常有限,当然,你可以绕过去,直接大家都走服务器端结合 WebSocket 来实现跟主线程,但 WebWorker 本身能跟主线程通过消息机制来交互确实会更方便些,如果再允许提交对于 DOM 的操作就更好了。

WebWorker 通过 postMessage 来发送消息,通过 message 事件来接受接收消息。其中发送的数据就在 event.data 中。

比如上面的代码,由于 worker.js 是通过主线程的代码加载的,所以执行顺序定然晚于主线程的代码执行,当 worker.js 中的代码执行后,可以通过向主线程发送一个消息,告诉主线程一切就绪,可以开始开始正常交互了.

这里需要知道的就是 在 worker 中没有 window 实例,也没有全局的 this,但是却有着 WorkerGlobalScope 也就是 self,当前 worker 自己。

1 self.postMessage('ready');

在主线程中通过事件处理程序接收消息

1 worker.addEventListener('message', function (event) {
2     console.log(event.data);
3 });

另外,所有跟 worker 线程交互的代码也最好在收到 ·ready· 这个消息之后进行。因为此时 worker 线程已经就绪,而且可以在发送 ready 消息之前把必备的准备工作做好。

还有就是消息不要真的就发送简单的字符串,除非系统里面确实就是这种需求,最好设计下数据结构,采用统一的方式来做消息交互,比如类似下面这样或者别的方式都行:

{
    cmd: '',
    payload: ...
}

要进行错误处理,在主线程和在 worker 中做法很相似,都是添加 “error”事件处理程序,不同的是用 worker 实例还是 WorkerGlobalScope 也就是 self。

1 worker.addEventListener('error', function (event) {
2     console.log('在主线程内监听 worker 实例的错误');
3 });
4 
5 self.addEventListener('error', function (event) {
6     console.log('在 worker 线程内监听当前 worker 的错误');
7 });

类似在 html 文档中可以使用 <script> 标记导入外部脚本,在 worker 里面也可以导入外部脚本,用法如下:

1 importScripts('script1.js', 'script2', ....);  // 可以导入一个到多个,省略号不是代码,这行只算是伪代码

最后用完了 worker 就可以把它关闭了,在主线程中用 terminate,在 worker 线程中直接用用 close 就可以了,用不到时就应该即使关闭,多少能省点系统资源。

1 worker.terminate(); // 在主线程中关闭当前 worker
2 self.close(); // 在 worker 中关闭自己

 

posted @ 2018-12-28 01:54  Baocang  阅读(2219)  评论(0编辑  收藏  举报