js多线程(worker)
Posted yezi-dream
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
以上是关于js多线程(worker)的主要内容,如果未能解决你的问题,请参考以下文章