H5 worker 系列一 基础知识

参考
阮一峰 Web Worker 使用教程
web worker详解
youtube上worker视频,完整代码

如我们所知,JavaScript 一直是属于单线程环境,我们无法同时运行两个 JavaScript 脚本;但是试想一下,如果我们可以同时运行两个(或者多个)JavaScript 脚本,一个来处理 UI 界面(一直以来的用法),一个来处理一些复杂计算,那么程序的整个架构将会发生很多变化,我们的任务将更有区分性和条理性,同时可以更充分利用设备的硬件计算能力(多核运算),这将大大有利于提高我们的页面性能。

在 HTML5 的新规范中,实现了 Web Worker 来引入 JavaScript 的 “多线程” 技术,他的能力让我们可以在页面主运行的 JavaScript 线程中加载运行另外单独的一个或者多个 JavaScript 线程;这并不意味着 JavaScript 语言本身就支持了多线程,对于 JavaScript 语言本身它仍是运行在单线程上的, Web Worker 只是浏览器(宿主环境)提供的一个能力/API。

Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。

H5 worker 系列一 基础知识_第1张图片
浏览器支持
一、快速创建

1.创建 web worker 文件

//my_worker.js
var i = 0;
function timedCount(){
    for(var j = 0, sum = 0; j < 100; j++){
        for(var i = 0; i < 100000000; i++){
            sum+=i;
        };
    };
    //将得到的sum发送回主线程
    postMessage(sum);
};
//将执行timedCount前的时间,通过postMessage发送回主线程
postMessage('Before computing, '+new Date());
timedCount();
//结束timedCount后,将结束时间发送回主线程
postMessage('After computing, ' +new Date());

以上代码中重要的部分是 postMessage() 方法 - 它用于向 HTML 页面传回一段消息。
注释:web worker 通常不用于如此简单的脚本,而是用于更耗费 CPU 资源的任务。

2.创建 Web Worker 对象

//webWorker.html

    
        worker
        
        
    
    
        

当 web worker 传递消息时,会执行事件监听器中的代码。event.data 中存有来自 event.data 的数据。

3.结果

Before computing, Tue Oct 16 2018 17:30:16 GMT+0800 (中国标准时间)
499999990094761700
After computing, Tue Oct 16 2018 17:30:29 GMT+0800 (中国标准时间)

4.终止 Web Worker
当我们创建 web worker 对象后,它会继续监听消息(即使在外部脚本完成之后)直到其被终止为止。如需终止 web worker,并释放浏览器/计算机资源,请使用 terminate() 方法:w.terminate();被终止的Worker将不再响应任何信息或执行任何其他的计算。终止之后,Worker不能被重新启动,但可以使用同样的URL创建一个新的Worker。
以下参考w3c HTML 5 Web Workers





Count numbers:



二、注意事项

1.由于 web worker 位于外部文件中,它们无法访问下列 JavaScript 对象:

  • window 对象
  • document 对象
  • parent 对象

worker.js执行的上下文,与主页面html执行时的上下文并不相同,最顶层的对象并不是window,woker.js执行的全局上下文,是个叫做WorkerGlobalScope的东东,所以无法访问window、与window相关的DOM API,但是可以与setTimeout、setInterval等协作。
具体参考worker 支持的函数

2.可以获取到部分浏览器提供的 API :

  • setTimeout(), clearTimeout(), setInterval(), clearInterval():有了这几个函数,就可以在 Worker 线程中执行定时操作了;
  • XMLHttpRequest 对象:意味着我们可以在 Worker 线程中执行 ajax 请求;
  • navigator 对象:可以获取到 ppName,appVersion,platform,userAgent 等信息;
  • location 对象(只读):可以获取到有关当前 URL 的信息;

3.脚本限制
Worker 线程不能执行alert()方法和confirm()方法。分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。

4.文件限制
Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。

5.在 Worker 中加载外部脚本
Worker 内部如果要加载其他脚本,有一个专门的方法importScripts()。

// main.js
var worker = new Worker('./worker1.js');
// worker1.js
console.log('hello, I,m worker 1');
importScripts('worker2.js', 'worker3.js');
// 或者
// importScripts('worker2.js');
// importScripts('worker3.js');
// worker2.js
console.log('hello, I,m worker 2');
// worker3.js
console.log('hello, I,m worker 3');

在这里,我们在 main.js 中运行了 worker1.js 线程,然后在 worker1.js 中加载了 worker2.js 和 worker3.js,在 console 中,可以看到他们全部执行了。

在WebWorker实战使用(简体版如果图片打不开,可以看繁体版WebWorker實戰使用)中,作者表示:

实际开发中我们不会把所有的代码都放在一个文件中让子线程加载,肯定会选择模块化开发。官方提供的方式是使用importScripts,但是这个在实际开发中很不实用,importScripts的加载方式是阻塞式的,所以我们最好用打包工具将所有worker中需要的文件打包成一个文件。这里我推荐browserify/webworkify,这是webpack的一个插件。对于webworkify-webpack的原理其实并没有使用importScripts而是使用另一种方式来创建worker,将js代码stringify后创建Blob对象,然后又createObjectURL创建对象url来实例化worker。类似如下过程:

H5 worker 系列一 基础知识_第2张图片
image.png

参考上面的方式,可以把主线程和worker的代码放在同个网页上面。


  
    
  

上面是一段嵌入网页的脚本,注意必须指定

你可能感兴趣的:(H5 worker 系列一 基础知识)