js多线程(worker)

    浏览器端js是单线程执行,所以当js执行高负载运算时,UI渲染就会阻塞,页面就会出现卡顿,用户体验就不是很好

    js为此也提供了异步操作,例如: 定时器(setTimeout 和 setInterval),Ajax请求等,但异步终究还是单线程,不能从根本上解决问题,像setTimeout并不能拿到正确的值,因为执行的时候将该任务放到主线程执行,只有当前面的任务执行完才开始执行,所以即使设置时间为0,也并不一定立刻执行

   所以HTML5标准添加了Web Worker,worker允许一段js程序运行在主线程之外的线程,子线程与主线程互不干扰,当子线程的代码执行完成,将结果返回给主线程,主线程接收到相应结果后再做对应处理,当有一些计算密集型或高延迟的任务就可以交给worker子线程来负担,主线程就不会阻塞

   worker是window对象的一个方法,一个worker对象可通过构造函数(window.worker())来创建,创建对象时,需要传给构造函数一个js文件,该文件包含了放到子线程中运行的代码

   worker通过postMessage()和onmessage = () => {} 来进行通信,主线程和子线程通信是双向的,都有可以发送和接收信息,postMessage传递的数据都是拷贝传递(ArrayBuffer除外)

   子线程运行耗损系统资源,所以当执行完毕后,我们可以手动关闭子线程

    在主线程中关闭: worker.terminate()

    在子线程中关闭: self.close()  (在子线程中window需改写成self,下文有解释)

   

     worker限制

     1)同源

        分配给worker子线程运行的脚本文件,必须与主线程的脚本文件同源,包括协议,域名和端口,不支持本地地址(file://);

        当使用CDN来存储js文件时,主线程与子线程就会出现跨域

        解决方法: 【1】将子线程的脚本转换成Blod对象

                        【2】然后给Blod对象创建一个URL

                        【3】将这个URL传给worker的构造函数

       示例代码: 

          var workerBlob = new Blob(['(' + function +')()'], { type: "text/javascript" });

          var url = window.URL.createObjectURL(workerBlob);

          var worker = new Worker(url);

    2) 访问 

        worker子线程所在的全局对象,与主线程不在一个上下文环境,所以无法读取主线程所在网页的DOM,无法使用document,window,parent这些对象,global指向有变更,window需要改写成self,不能执行alert()和comfire()的方法,只能读取部分navigator对象内的数据

   3)使用异步

        worker子线程中支持js的异步操作,但仍然不可以跨域

 

    worker的兼容性还不错,但不兼容IE9

 

  

posted @ 2018-12-31 23:13  yezi-dream  阅读(12250)  评论(0编辑  收藏  举报