web worker 详细介绍

1、简介

我们都知道javaScript是采用单线程执行的,同一时间只能做一件事,如果采用同步执行的,出现阻塞那么后面的代码将不会执行,HTML5则提出了Web Worker标准,表示js允许多线程,但是子线程完全受主线程控制并且不能操作dom,只有主线程可以操作dom,所以js本质上依然是单线程语言。
关于js的运行机制可以参考阮一峰文章JavaScript 运行机制详解:再谈Event Loop

2、web worker

web worker就是在js单线程执行的基础上开启一个子线程,进行程序处理,而不影响主线程的执行,当子线程执行完之后再回到主线程上,在这个过程中不影响主线程的执行。

2.1、创建线程

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

其中的worker.js是一个单独的js文件,以上代码创建了一个子线程,还可以使用下面的方式

var worker = new Worker(blob);

传入的参数

  • 一个指向 js文件资源的url
  • Blob 对象,就是一个包含只读原始数据类文件对象

2.2、线程间通信

web worker的基本原理是在当前的主线程中加载一个只读文件,来创建一个新的线程,两个线程同时存在且互补阻塞,并且子线程与主线程之间提供了数据交互的接口postMessageonmessage,来进行数据发送和接收。

2.2.1、数据发送

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

// 第一种传递方式
worker.postMessage(message, transferList);

// 第二种方式
worker.postMessage({
    operation:'list_all_users',
    // ArrayBuffer Object
    input:buffer,
    thresold:0.8,
}, [buffer]);

如果要想一个专用线程发送数据,那么我们需要使用线程中的 postMessage 方法。专用线程不仅仅支持传输二进制数据,也支持结构化的 JavaScript 数据格式。在这里有一点需要注意,为了高效地传输 ArrayBuffer 对象数据,需要在 postMessage 方法中的第二个参数中指定它。

2.2.2、数据接收

//方法一
worker.onmessage = function(event){
    var data = event.data;        //通过event.data来获取传入的参数
}

//方法二
worker.addEventListener("message",target);

2.2.3、示例代码

下面是一段运行在chrome中的参数传递方式:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webWorker</title>
</head>
<body>
    <script>
        var worker = new Worker("worker.js");
        worker.postMessage("123456");

        worker.onmessage = function (e) {
            console.log(e.data)
        };
    </script>
</body>
</html>

worker.js

onmessage = function (e) {
    console.log(e.data);
    postMessage("2222")
};

此时我们的浏览器打印出的log是如下:
这里写图片描述

2.2.4、异常处理

worker.onerror = function(e){
    console.log("error at "+e.filename ":" + e.lineno + e.message)
}

2.2.5、结束线程

worker.terminate();

3、worker 作用域

当我们创建一个新的worker时,改代码会运行在一个全新的javascript的环境中(WorkerGlobalScope)运行,是完全和创建worker的脚本隔离,这时我们可以吧创建新worker的脚本叫做主线程,而被创建的新的worker叫做子线程。

WorkerGlobalScopeworker的全局对象,所以它包含所有核心javascript全局对象拥有的属性如JSON等,window的一些属性,也拥有类似于XMLHttpRequest()等。

但是我们所开启的新的worker也就是子线程,并不支持操作页面的DOM

4、SharedWorker 共享线程

共享线程是为了避免线程的重复使用和销毁过程,降低了系统性能的消耗,共享线程SharedWorker可以有多个页面的线程链接。

使用SharedWorker创建共享线程,也需要提供一个javascript脚本文件的URL地址或Blob,该脚本文件中包含了我们在线程中需要执行的代码,如下:

var worker = new SharedWorker('sharedworker.js');

共享线程也使用了message事件监听线程消息,但使用SharedWorker对象的port属性与线程通信如下。

worker.port.onmessage = function(e){
    ...
}

同时我们也可以使用SharedWorker对象的port属性向共享线程发送消息如下。

worker.port.postMessage("message");

摘录

文章大部分类容摘自《指尖上行》一书

参考文献

1、JavaScript 运行机制详解:再谈Event Loop
2、深入 HTML5 Web Worker 应用实践:多线程编程

猜你喜欢

转载自blog.csdn.net/ithanmang/article/details/82622420