JavaScript是单线程的,但WebWorkers规范允许Web应用程序可以在独立于主线程的后台线程中,创建子线程,运行一个脚本操作,从而可以在独立的线程中执行费时的处理任务,进而不会阻塞主线程(通常是UI线程),Worker线程计算结束后,再把结果返回给主线程,这样就解决了Javascript运行时会干扰用户界面的问题;
例如:
divid="sult"/divscriptvarsult=document.getElementById("sult");varworker=newWorker("worker.js");worker.onmessage=function(event){sult.innerText=event.data;};/script
worker.js:
varnum=0;setInterval(function(){postMessage(num++);},);
浏览器实现WebWorkers的方式有多种,可以使用线程、后台进程或者运行在其他处理器核心上的进程等等;WebWorkers起初是作为HTML5标准的一部分,但后来独立成一个相近的标准;IE9及以下不支持Workers。
应用场景:WebWorkers的实现为Web应用带来了后台计算的能力,它可以将一些耗时的数据处理操作从主线程中剥离,从而极大减轻了因计算量大造成的UI阻塞而出现的界面渲染卡、掉帧的情况,使主线程更加专注于页面渲染和交互,更大程度地利用了终端硬件的性能;
其应用的场景:数学运算、大数据处理、懒加载、文本分析、流媒体数据处理、canvas图形绘制、图像处理等等。
专用Worker和共享Worker:
worker有两大类,一个是专用Worker(dedicatedworker),是专门为某个特定的页面服务的;二是共享Worker(shadworker),这种worker可以在浏览器的多个标签中打开的同一个页面间共享。
专用Worker:
只能由生成它的脚本所使用;
一个Worker包含两部分,一部分是Worker对象,该对象用于创建worker线程;第二部分是DedicatedWorkerGlobalScope,这是一个用来表示新创建的Worker内部的全局对象,也就是Worker线程内部使用的上下文对象;
使用Worker(URL[,options])构造函数实例化Worker对象,该对象执行指定的URL脚本;
worker.js线程:
console.log("myisworker");
主线程:
varworker=newWorker("worker.js");console.log(worker);//Worder
参数URL指定的JavaScript文件,包含了将运行独立于主线程的worker线程中运行的代码;
参数URL指定的workerJS文件必须遵守同源策略,如果该URL是一个无效的URL,或者违反同源策略,将抛出SECURITY_ERR异常;如果此URL的MIME类型不是text/javascript类型,将抛出NetworkError异常;如果URL无法解析,将引发SyntaxError异常;
参数options是可选的配置对象,可用属性如下:
type:指定worker类型的字符串,可能的值是classic或module,如果未指定,将使用默认值classic;cdentials:用以指定worker凭证的字符串,可能的值是omit(不要求凭证)、same-origin或include,如果未指定,或者type是classic,将使用默认值omit;name:用于指定Worker的名称,用来区分多个Worker线程,主要用于调试目的;
如主线程:
varworker=newWorker("worker.js",{type:"classic",cdentials:"omit",name:"myWorker"});console.log(worker);
虽然可以在参数中指定options,但该参数的值只能在Worker线程中才能访问;如,Worker线程:
postMessage({name:self.name,type:self.type,cdential:self.cdential});
主线程:
worker.onmessage=function(event){console.log(event.data);};
worker线程和主线程之间的数据传递,是通过这样的消息机制进行的:双方都使用postMessage()方法发送各自的消息,再使用onmessage事件处理函数来响应消息,且消息被包含在onmessage事件的data属性中;
当页面在Worker对象上调用postMessage()时,数据会以异步方式被传递给worker线程,进而触发worker线程中的message事件;
它们的通信是双向的,反过来也是一样;
使用Worker对象的postMessage(message[,transferList])方法向worker传递消息,参数message为要发送的消息数据,参数transferList是可选的,它是一个Transferable对象的数组,用于转移所有权;如主线程:
worker.postMessage("wangwei");
Worker线程是通过onmessage和onerror事件来接收数据和处理错误的,如:
onmessage=function(event){console.log(event);//MessageEventconsole.log(event.data);}onerror=function(event){console.log(event);}
该事件类型是MessageEvent类型;
worker线程向主线程传递消息:
与主线程向worker线程传递消息一样,只不过由worker线程通过postMesage()发送消息,主线程通过onmessage和onerror事件接收鼠数据,如,主线程:
worker.onmessage=function(event){console.log("Main:"+event.data);};worker.onerror=function(event){console.log(event);}
worker线程:
postMessage("我是worker线程");
参数message可以是任何能够被序列化的值,也可以是对象,如:
worker.postMessage({type:"