worker使用场景
js是单线程运行的,在遇到一些需要处理大量数据的js时,可能会阻塞页面的加载,造成页面的假死。这时我们可以使用worker来开辟一个独立于主线程的子线程来进行哪些大量运算。这样就不会造成页面卡死。也说明 worker可以用来解决大量运算是造成页面卡死的问题。
worker语法
const worker=new Worker(aURL, options)
它有两个参数:
aURL(必须)是一个DOMString 表示worker 将执行的脚本的URL。它必须遵守同源策略。
options (可选)它的一个作用就是指定 Worker 的名称,用来区分多个 Worker 线程
worker的属性
Worker.onerror:指定 error 事件的监听函数
Worker.onmessage:指定 message 事件的监听函数,发送过来的数据在Event.data属性中。
Worker.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
worker的方法
Worker.postMessage():向 Worker 线程发送消息。
Worker.terminate():立即终止 Worker 线程。
使用worker的注意点
1.同源限制 分配给 Worker 线程运行的脚本文件,必须与主线程的脚本文件同源。
2.DOM 限制 Worker 线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的 DOM 对象,也无法使用document、window、parent这些对象。但是,Worker 线程可以navigator对象和location对象。
3.通信联系 Worker 线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过消息完成。
4.脚本限制 Worker 线程不能执行alert()方法和confirm()方法,但可以使用 XMLHttpRequest 对象发出 AJAX 请求。
5.文件限制 Worker 线程无法读取本地文件,即不能打开本机的文件系统(file://),它所加载的脚本,必须来自网络。
实现将worker主线程与子线程代码放在同一个文件中
通常情况下,Worker 载入的是一个单独的 JavaScript 脚本文件,但是也可以载入与主线程在同一个网页的代码。
<script id="worker" type="app/worker"> //*type要指明一个浏览器不认识的类型
self.onmessage = function (event) { //子线程接收主线程传递数据触发的方法
var data = event.data;
var ans = fibonacci(data);
this.postMessage(ans); //向主线程提交请求完成后或处理后的数据
};
function fibonacci(n) { //子线程要执行的方法,一般是请求大量数据,这里是一个递归方法
return n < 2 ? n : arguments.callee(n - 1) + arguments.callee(n - 2);
}
</script>
<script>
var blob = new Blob([document.querySelector('#worker').textContent]);// 转码
var url = window.URL.createObjectURL(blob); // 编译为url
var worker = new Worker(url); //因为worker只能请求网络数据.所以需要编译为url
worker.postMessage(40);//向子线程传数据
worker.onmessage=function(event){ // 接收子线程传递的数据
var data=event.data;
console.log(data) //打印
};
worker.onerror=function(event){ // 遇到错误时触发 ,打印错误信息查看
console.log(event.fileName,event.lineo,event.message);
};
</script>
self代表子线程,即子线程的全局对象,因为在不同的上下文中,也可以使用this指代
上面是一段嵌入网页的脚本,注意必须指定<script>
标签的type属性是一个浏览器不认识的值,上例是app/worker,先将嵌入网页的脚本代码,转成一个二进制对象,然后为这个二进制对象生成 URL,再让 Worker 加载这个 URL。这样就做到了,主线程和 Worker 的代码都在同一个网页上面。