HTML5之worker开启JS多线程模式及window.postMessage跨域

  • worker概述
  • worker基本使用
  • window下的postMessage
  • worker多线程的应用

 1、worker概述

web worker其实是开启js异步执行的一种方式。在html5以前有事件、定时器、http请求三种异步机制,js自己并不能主动将一块代码使用异步的方式执行,worker的出现填补了js在非事件、定时器、http请求的状况下能够主动开启js代码的异步执行。worker有本身独立的线程,并不是像前面三个异步机制那样的回调函数。因此,worker线程一旦创建成功,就会始终运行,并不会像前面三个异步机制那样被主线程打断,主线程与辅助线程(worker)之间经过消息事件通信。html

web worker相关手册与博客:html5

阮一峰网络日志:http://www.ruanyifeng.com/blog/2018/07/web-worker.htmlweb

MDN手册:https://developer.mozilla.org/zh-CN/docs/Web/API/Worker跨域

developer博客:https://www.developer.com/lang/jscript/7-things-you-need-to-know-about-web-workers.html网络

上一篇博客的翻译版:https://blog.csdn.net/shenlei19911210/article/details/49779613多线程

web worker使用注意事项:

1.同源限制:分配worker线程运行脚本文件,必须与主线程的脚本文件同源。异步

2.DOM限制:worker线程所在的全局对象,与主线程不同,不能读取所在网页的DOM对象,也没法使用document 、 window 、parent这些对象。可是worker线程可使用navigator对象和location对象。ide

3.通讯联系:worker线程和主线程不在同一个上下文环境,它们不能直接通讯,必须经过消息完成。函数

4.脚本限制:worker线程不能执行alert()方法和cnfirm()方法,但可使用XMLHttpRequest对象发送AJAX请求。post

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

 2、worker的基本使用

2.1在主线程中开启一个辅助线程:

var worker = new Worker('./worker.js'); //在主线程的中开启辅助线程(传入辅助线程的文件路径)

2.2主线程向辅助线程发送消息:

1 var data = {type:'sum',num:1000}//测试Function类型的值不能传递
2 worker.postMessage(data);//经过postMessage方法传递给辅助线程

2.3辅助线程接收主线程的消息:

1 this.onmessage = function(e){//在辅助线程中经过onmessage事件监听主线程postMessage发送过来的消息
2     console.log(e);//经过事件元对象中的data接收主线程发送过来的数据
3     console.log(e.data.num)
4 }

2.4.辅助线程向主线程提交工做(第5行代码):

 1 this.onmessage = function(e){//在辅助线程中经过onmessage事件监听主线程postMessage发送过来的消息
 2     var submitWorker = null;
 3     if(e.data.type == 'sum'){
 4         submitWorker = sum(e.data.num); //辅助线程处理业务
 5         this.postMessage(submitWorker); //辅助线程经过postMessage方法向主线程提交工做
 6     }
 7 }
 8 function sum(num){
 9     var sumVal = 0;
10     for(var i = 0; i < num; i++){
11         sumVal +=i;
12     }
13     return sumVal;
14 }

2.5主线程接收辅助线程的工做:

1 worker.onmessage = function(e){//主线程经过onmessage监听接收辅助线程的消息
2     console.log(e);// 一样经过事件元对象的data获取辅助线程传递过来的数据
3     console.log(e.data);//499500
4 }

2.6主线程辞退辅助线程与辅助线程主动关闭线程:

1 worker.terminate(); //主线程主动关闭辅助线程worker (辞退后不在接收辅助线程的消息)
2 this.close(); //辅助线程主动关闭线程(关闭后再也不向主线程发送消息)

以上示例的所有代码,请注意须要在网络服务下测试,由于worker必须来自网络。

 1 //indexWorker.html(主线程代码)
 2 <!DOCTYPE html>
 3 <html>
 4 <head>
 5     <meta charset="utf-8">
 6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 7     <title>worker</title>
 8     <link rel="stylesheet" href="">
 9 </head>
10 <body>
11     <script>
12         var worker = new Worker('./worker.js');
13         var data = {
14             type:'sum',
15             num:1000
16         }
17         worker.postMessage(data);//主线程向辅助线程发送消息
18         worker.onmessage = function(e){//主线程接收辅助线程的消息
19             console.log(e);// 一样经过事件元对象的data获取辅助线程传递过来的数据
20             console.log(e.data);//499500
21             // worker.terminate(); //主线程主动关闭辅助线程worker
22         }
23 
24     </script>
25 </body>
26 </html>
27 
28 //worker.js(辅助线程脚本代码)
29 this.onmessage = function(e){//在辅助线程中经过onmessage事件监听主线程postMessage发送过来的消息
30     // console.log(e);//经过事件元对象中的data接收主线程发送过来的数据
31     var submitWorker = null;
32     if(e.data.type == 'sum'){
33         submitWorker = sum(e.data.num); //辅助线程处理业务
34         this.postMessage(submitWorker); //辅助线程经过postMessage方法向主线程提交工做
35     }
36     // this.close(); //辅助线程主动关闭线程(关闭后再也不向主线程发送消息)
37 }
38 function sum(num){
39     var sumVal = 0;
40     for(var i = 0; i < num; i++){
41         sumVal +=i;
42     }
43     return sumVal;
44 }
示例代码(两个文件的代码,注意本身拆分)

2.7worker中引入其余脚本:

1 importScripts('script1.js'); //能够在辅助线程脚本中经过importScripts引入其余脚本
2 importScripts('script1.js', 'script2.js');//而且能够同时加载多个脚本

好比能够经过脚本引入的方式来拆分上面的worker.js文件==》

 1 //worker.js文件
 2 importScripts('./workerMath.js'); //经过importScripts()方法引入其余脚本文件
 3 this.onmessage = function(e){//在辅助线程中经过onmessage事件监听主线程postMessage发送过来的消息
 4     // console.log(e);//经过事件元对象中的data接收主线程发送过来的数据
 5     var submitWorker = null;
 6     if(e.data.type == 'sum'){
 7         submitWorker = sum(e.data.num); //辅助线程处理业务
 8         this.postMessage(submitWorker); //辅助线程经过postMessage方法向主线程提交工做
 9     }
10     // this.close(); //辅助线程主动关闭线程(关闭后再也不向主线程发送消息)
11 }
12 
13 //workerMath.js文件
14 function sum(num){
15     var sumVal = 0;
16     for(var i = 0; i < num; i++){
17         sumVal +=i;
18     }
19     return sumVal;
20 }
View Code

 3、window下的postMessage

MDN手册:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

window下的postMessage与worker中的postMessage的功能基本一致,只不过一个是实现js脚本线程之间的通讯,一个是实现两个网页之间的通讯。window中的postMessage主要被应用与解决主窗口与iframe子窗口中的数据传递,而且能够实现跨域通讯。

示例:

 1 //父窗口代码
 2 <iframe src="./winPostMessage.html"></iframe>
 3 <script>
 4     window.onmessage = function(e){
 5         console.log(e);
 6         console.log(e.data.name);//他乡踏雪
 7     }
 8 </script>
 9 
10 //子窗口代码
11 <script>
12     window.parent.postMessage({name:"他乡踏雪"},'http://localhost/')
13 </script>

postMessage语法:

otherWindow.postMessage(message, targetOrigin, [transfer]);

otherWindow:窗口引用,好比window.parent、window.iframes[n];

message:须要传递的数据,不能使用function;

targetOrigin:可使用URL(如示例中,窗口协议、主机地址、端口必须一致),也能够直接使用窗口对象模型的引用,好比示例中参数也可使用window.parent。

[transfer]:(暂时还不了解其如何使用)

onmessage事件

window.addEventListener("message", receiveMessage, false);

message除了示例中的data接收postMessage传递的数,还有origin携带了传递数据的窗口的URL,以及source携带的传递数据的窗口对象模型。

相关文章
相关标签/搜索