26
2017
09

webWoker

    它允许开发人员编写能够长时间运行而不被用户所中断的后台程序,
    去执行事务或者逻辑,并同时保证页面对用户的响应。    
WorkerGlobalScope作用域下的常用属性、方法如下:
    1、self  我们可以使用 WorkerGlobalScope 的 self 属性来或者这个对象本身的引用
    2、location 属性返回当线程被创建出来的时候与之关联的 WorkerLocation 对象,
    它表示用于初始化这个工作线程的脚步资源的绝对 URL,
    即使页面被多次重定向后,这个 URL 资源位置也不会改变。
    3、close   关闭当前线程,与terminate作用类似
    4、importScripts   我们可以通过importScripts()方法通过url在worker中加载库函数
    5、XMLHttpRequest  有了它,才能发出Ajax请求
    6setTimeout/setInterval以及addEventListener/postMessage


关于worker    我们可以做什么:

   1.可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信
  2.可以在worker中通过importScripts(url)加载另外的脚本文件
  3.可以使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()
  4.可以使用XMLHttpRequest来发送请求
  5.可以访问navigator的部分属性

局限性:

  1.不能跨域加载JS
  2.worker内代码不能访问DOM
  3.各个浏览器对Worker的实现不大一致,
    例如FF里允许worker中创建新的worker,而Chrome中就不行
  4.IE这个新特性

Js单线程


<script> //添加到任务队列中,待同步任务所处的‘执行栈’执行完毕,1秒后执行任务队列中的这个匿名函数 setTimeout(function(){ console.log('come on'); },1000); //只要不关闭该alert,‘执行栈’就没结束,从而也就不会进入到任务 "队列 " 中 alert('waiting'); </script>

创建一个Worker对象

  <script>
    function init(){
        //创建一个Worker对象,并向它传递将在新线程中执行的脚本url
        var worker = new Worker('worker.js');
        //接收worker传递过来的数据
        worker.onmessage = function(event){         document.getElementById('result').
        innerHTML+= event.data
        };
    };
    </script>
    JS代码
        var i = 0;
    function timedCount(){
        for(var j = 0, sum = 0; j < 100; j++){
            for(var i = 0; i < 100000000; i++){
                sum+=i;
            };
        };
        //将得到的sum发送回主线程
        postMessage(sum);
    };
    //将执行timedCount前的时间,通过postMessage发送回主线程
    postMessage('Before computing, '+new Date());
    timedCount();
    //结束timedCount后,将结束时间发送回主线程
    postMessage('After computing, ' +new Date());

terminate onerror

(function init() {
    var worker = new Worker('worker.js');
    //每隔100毫秒,向子线程传递{name: 'monkey'}信息
    setInterval(function() {
        worker.postMessage({
            name: 'monkey'
        });
    }, 1000);

    //当主线程worker收到来自子线程的消息后,触发message事件
    worker.onmessage = function(event) {
        document.getElementById('result').innerHTML += event.data + "<br/>";
        //主线程使用terminate方法中断与子线程来往,在浏览器中只能显示一次event.data
        worker.terminate();
    };

    worker.onerror = function(e) {
        //打印出错消息
        console.log(e.message);
        //中断与子线程的联系
        worker.terminate();
    }
})();

    wokers.js
    alert("asdf");
    onmessage = function(event){
       postMessage(event.data.name);
    };

报错原因是alert为window对象的方法,所以会报错undefined。
worker.js执行的上下文,与主页面html执行时的上下文并不相同,
最顶层的对象并不是window,woker.js执行的全局上下文,是个叫做WorkerGlobalScope的东东,
所以无法访问window、与window相关的DOM API,但是可以与setTimeout、setInterval等协作。

snow

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css"> body,html{ height: 100%; } </style>
</head>
<body>
<script type="text/javascript"> var i = 0; var sw = new Worker("snowWorker.js"); sw.onmessage = function (e) { if(e.data < 0){ //worker 发送-1的时候是 创建雪花 createSnow(i); //通知worker开始 计算下落 sw.postMessage(i); i++; }else{ //雪花下落 snowDown(e.data); } } //创建一个雪花 function createSnow(id){ var one = document.createElement("div") var cha = document.body.clientWidth - one.offsetWidth var rand = Math.floor(Math.random() * cha) document.body.appendChild(one) one.style.position = "absolute"; one.style.top = "-10px"; one.style.zIndex = "5000px"; one.style.fontSize = "40px"; one.style.left = rand + "px"; one.innerHTML = "❄"; one.id = id; } //雪花下落 function snowDown (id) { var a = document.getElementById(id); a.style.top = a.offsetTop + 5 +"px" if (a.offsetTop > document.body.clientHeight) { document.body.removeChild(a); sw.postMessage("r" + id); } } </script>
</body>
</html>
//每过200毫秒通知前台页面产生一个雪花
setInterval(function(){
    self.postMessage(-1);
},200);

var interArray = [];

//前台页面雪花产生之后,将id发送给worker,同时worker开启一个计时器,每过50毫秒通知前台,雪花位置移动
self.onmessage = function(e){
    var msg = e.data.toString();

     // msg.indexOf('r') 字符串中找不到r 为 -1;找到则返回相应的位置 
    if(msg.indexOf('r') != -1){
        clearInterval(interArray[parseInt(msg.replace("r",""))]);
        //console.log(msg);
    }else{
        interArray[msg] = setInterval(function(){
            this.postMessage(msg);
        },50);
    }
}
上一篇:Git:warning: ignoring broken ref refs/remotes/origin/HEAD 下一篇:Debian下用Glade开发一个简单的计算器