web无插件的线程处理机制(Worker机制)

JavaScript运行在单线程环境中,加入Worker后即变成了多线程(一个Worker对应一个线程?),但是Woker线程不能访问浏览器的资源,只有主线程才可以访问浏览器的资源。所以在web中对setTimeout/setInterval、ajax和dom事件的异步处理一般依赖事件循环来实现。

1.Web Worker是什么

Web Worker是HTML5标准的一部分,这一规范定义了一套API,它允许一段JavaScript程序运行在主线程之外的另外一个线程中。Web Worker规范中定义了两类工作线程,分别是专用线程Dedicated Worker(只能为一个页面所使用),共享线程Shared Worker(可以被多个页面所共享)。下面将的是专用线程

2.API案例

main.js

var worker=new Worker('task.js');//通过调用构造函数,传入worker脚本文件名,新建一个worker对象
worker.postMessage({id:1,msg:'hello world'});//调用该方法与新创建的工作线程通信,这里传入了一个json对象
worker.onmessage=function(message)//定义了worker对象的onmessage事件,当worker线程返回数据时,onmessage回调函数执行
{
var data=message.data;//数据封装在message参数的data属性中
console.log(JSON.stringify(data));
worker.terminate();//调用worker的terminate()方法可以终止worker线程的运行
};
worker.onerror=function(error)//当worker线程执行出错时,onerror回调函数执行
{
console.log(error.filename,error.lineno,error.message);//error参数中封装了错误对象的文件名,出错行号和具体错误信息
}

Dedicated Worker所执行的代码:task.js

//在工作线程代码中,onmessage事件和postMessage方法在其全局作用域可以访问
onmessage=function(message)//定义了onmessage事件处理函数,由主线程传入的数据封装在message对象的data属性中
{
var data=message.data;
data.msg='He from task.js';
postMessage(data);//数据处理完之后通过postMessage方法完成与主线程的通信。
}

3.worker线程执行流程

3.1 Worker线程的创建是异步的

代码执行到new Worker时,在内核中构造WebCore::JSWorker对象(JSBbindings层)以及对应的WebCore::Worker对象(WebCore模块),根据初始化的url地址,发起异步加载的流程,主线程代码不会阻塞在这里等待worker线程去加载,执行指定的脚本文件,而是会立即向下执行下面的代码。

3.2 postMessage消息交互由内核调度

main.js中,在创建worker线程后,立即调用了postMessage方法传递了数据,在worker编程还没创建完成时,main.js中发出的消息会先存储在一个临时消息队列中,当异步创建worker线程完成,临时消息队列中的消息数据复制到worker对应的WorkerRunLoop的消息队列中,worker线程开始处理消息。在经过一轮消息来回后,继续通信时,这个时候因为worker线程已经创建,所以消息会直接添加到WorkerRunLoop的消息队列中。

4. worker线程数据通讯方式

主线程与子线程数据通信方式有很多种,通信内容可以是文本,也可以是对象。需要注意的是这种通信时拷贝关系,传值而不是传址,子线程对通信内容的修改,不会影响到主线程。事实上,浏览器内部的运行机制是先将通信内容串行化,然后把串行化后的字符串发给子线程,后者再将它还原。

传二进制数据:主线程与子线程之间可以交换二进制数据,比如File,Blob,ArrayBuffer等,用拷贝方式发送二进制数据会造成性能问题,比如,主线程向子线程发送一个50M的文件,默认情况下浏览器会生成一个源文件的拷贝,为解决此问题,JavaScript允许主线程把二进制数据直接转移给子线程,转移后主线程无法再使用这些数据,这是为了防止出现多个线程同时修改数据的问题,这种转移数据的方法叫做Transferable.

在worker线程中,可以获得下列对象:

  • navigator对象
  • location对象,只读
  • XMLHttpRequest对象
  • setTimeout/setInterval方法
  • Application Cache
  • 通过importScripts()方法加载其他脚本
  • 创建新的webWorker

worker线程不能获得下列对象

  • DOM对象
  • window对象
  • document对象
  • parent对象

上述规范限制了在worker线程中获得主线程页面相关对象的能力,在worker对象中不能进行dom元素的更新。

发布了38 篇原创文章 · 获赞 2 · 访问量 1521

猜你喜欢

转载自blog.csdn.net/qq_34754747/article/details/104370588