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


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

     一、worker概述

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

    web worker相关手册与博客:

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

    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对象。

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

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

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

     二、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

     三、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携带的传递数据的窗口对象模型。

  • 相关阅读:
    Java GC机制详解
    程序员面试的时候如何谈薪酬待遇?
    每个程序员都会遇到的面试问题:谈谈进程和线程的区别
    面试问题:你了解Java内存结构么(Java7、8、9内存结构的区别)
    UVa 208
    山科 STUST OJ Problem B: 编写函数:String to Double (II) (Append Code)
    山科SDUST OJ Problem J :连分数
    辗转相除法
    [比赛总结]ACM div3 G 比赛总结
    SDUST OJ Problem G 动态的字符串排序
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/11298750.html
Copyright © 2020-2023  润新知