这是我参与更文挑战的第9天,活动详情查看: 更文挑战。
Web Worker
背景
众所周知,JavaScript是单线程模型,所有的任务只能在同一条线程上进行完成,前边的任务未完成则后续任务只能等待,所以在H中引入了Web Worker,为JavaScript创建一个多线程的环境,将部分任务提供给它在后台运行,前台后台同时运行。
Web Worker是后台运行的JavaScript,它独立于其他脚本且不会影响页面的性能。引入Web Worker的好处是一些计算密集型或高延迟的任务,被 Web Worker 线程所处理,主线程就会很流畅,不会被阻塞或拖慢,而此时 Web Worker 在后台运行。但是这也正是 Web Worker 比较耗费资源的原因。
浏览器支持及使用
除了IE外所有主流浏览器均支持Web Worker。
可在创建Worker之前检测是否支持
if(typeof(Worker)!=="undefined") {
// 支持.....
}
else {
// 不支持..
}
Web Worker在一个独立的线程中运行,所以代码需要放在一个单独的文件中。加载时如果存在指定文件,浏览器会在文件下载完毕后执行,生成新的Worker线程,如果加载文件失败不会有任何提示。
创建Worker后利用postMessage()
启动
var worker = new Worker('worker.js');
var info = 'start worker!'
worker.postMessage(info);
在Worker中使用onmessge
事件接收主线程的消息来实现一些操作。
onmessage = function(e) {
var data = e.data
}
同样的,从Worker发消息到主线程也采用同样方法。
// Receive the message from the main thread
onmessage = function(e) {
var info = e.data;
var result = info + ' get';
postMessage(result);
};
停止Worker有两种方法,在主线程中调用worker.terminate()
或在内部调用self.close()
均可。在任务结束后一定要停止,因为Worker会一直在后台运行耗费资源,不应该过度使用。
注意事项
- 主线程与Worker之间传递的消息不是共享的,因为系统将消息对象传递给Worker后会将其序列化,在另一端再取消序列化。大部分浏览器通过JSON的编码解码实现。
- Worker的self和this都是Worker的全局作用域。
- Worker无法处理DOM,无法使用window对象、document对象等。
- Worker可以生成子Worker,但需要注意:子Worker必须和父线程处在相同origin中,其中的URI应相对于父Worker位置解析。
Cesium的异步+多线程
Cesium中涉及到大量三维球计算和大数据量交互,比如三角网,参数化Geometry等,都是在Worker中实现的,参数的传递以及不同类型对应的不同算法。
Cesium源码中Source\Core\TaskProcessor.js
内为Cesium封装的Worker。我们简单来看一下。
function TaskProcessor(workerPath, maximumActiveTasks) {
this._workerPath = new Uri(workerPath).isAbsolute()
? workerPath
: TaskProcessor._workerModulePrefix + workerPath;
this._maximumActiveTasks = defaultValue(
maximumActiveTasks,
Number.POSITIVE_INFINITY
);
this._activeTasks = 0;
this._deferreds = {};
this._nextID = 0;
}
TaskProcessor.prototype.scheduleTask = function (
parameters,
transferableObjects
) {
if (!defined(this._worker)) {
this._worker = createWorker(this);
}
// ……
return when(canTransferArrayBuffer(), function (canTransferArrayBuffer) {
// ……
return deferred.promise;
});
};
我们使用时只需要创建一个TaskProcessor,指定类型,然后调用scheduleTask,接收对应具体参数,然后返回一个Promise对象,我们可以异步的获取的对应结果。
使用方法:
var taskProcessor = new Cesium.TaskProcessor('myWorkerPath');
var promise = taskProcessor.scheduleTask({
someParameter : true,
another : 'hello'
});
if (!Cesium.defined(promise)) {
// too many active tasks - try again later
} else {
Cesium.when(promise, function(result) {
// use the result of the task
});
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!