Cesium之Web Workers

科技资讯 投稿 5600 0 评论

Cesium之Web Workers

1. 引言

浏览器是多进程的,每打开一个网页,都会开启一个渲染进程,渲染进程包含:

    GUI渲染线程 (有且只有一个
  • JS引擎线程 (有且只有一个
  • 事件触发线程
  • 定时器触发线程
  • 异步http请求线程

GUI渲染线程与JS引擎线程是互斥的,且JS引擎线程会先执行,如果JS代码卡住会导致GUI绘制卡住

    浏览器的进程与线程--深入同步、异步问题 - 知乎 (zhihu.com
  • Web Worker 之全面讲解 - 知乎 (zhihu.com

Web Workers就是创建JS代码执行的线程,使得JS代码执行能以多线程的方式执行,避免JS引擎线程卡住

Web Workers的解释可以参考:

    Web Workers API - Web API 接口参考 | MDN (mozilla.org
  • Web Worker 使用教程 - 阮一峰的网络日志 (ruanyifeng.com

2. Web Workers

通常而言,Web Workers包含:

    专用线程(Dedicated Workers)
  • 共享线程(Shared Workers)
  • 后台线程(Service Workers)等

Web Worker的大致的使用方法如下:

创建一个Web Worker:

const worker = new Worker('WebWorkerTest.js'
    WebWorkerTest.js是Web Worker执行的JS代码文件
  • 加载Web Worker执行的JS代码文件需要使用HTTP或HTTPS协议,即,需要搭建网络服务器

(在主线程里)向创建的Web Worker发送数据

worker.postMessage([2, 3]

(在子线程Web Worker,即WebWorkerTest.js中)接收主线程的数据、处理并发送给主线程

onmessage = function(e {
    console.log('Message received from main script'
    const workerResult = e.data[0] * e.data[1]
    console.log('Posting message back to main script'
    postMessage(workerResult
}

(在主线程里)接收Web Worker发送的数据

worker.onmessage = (e => {
      console.log("Result:", e.data
    }

综上,此处创建了两个文件:WebWorkerTest.jsWebWorkerTest.html

WebWorkerTest.html代码如下:

<body>
  <script>
    const worker = new Worker('WebWorkerTest.js'
    worker.postMessage([2, 3]
    worker.onmessage = (e => {
      console.log("Result:", e.data
    }
  </script>
</body>

WebWorkerTest.js代码如下:

onmessage = function(e {
    console.log('Message received from main script'
    const workerResult = e.data[0] * e.data[1]
    console.log('Posting message back to main script'
    postMessage(workerResult
}

运行结果如下(使用VS Code和Live Server插件):

    Web Workers API - Web API 接口参考 | MDN (mozilla.org
  • Web Worker 使用教程 - 阮一峰的网络日志 (ruanyifeng.com

3. Cesium中的Web Workers

Cesium源码中,对Web Workers进行了封装,封装为TaskProcessor

TaskProcessor使用示例为:

const taskProcessor = new Cesium.TaskProcessor('myWorkerPath';
const promise = taskProcessor.scheduleTask({
    someParameter : true,
    another : 'hello'
};
if (!Cesium.defined(promise {
    // too many active tasks - try again later
} else {
    promise.then(function(result {
        // use the result of the task
    };
}

查看源码,可以知道taskProcessor.scheduleTask(函数为:

TaskProcessor.prototype.scheduleTask = function (parameters, transferableObjects {
  // ...
  this._worker = createWorker(this;
  return Promise.resolve(canTransferArrayBuffer(.then(function (
    canTransferArrayBuffer
   {
    processor._worker.postMessage(
      {
        id: id,
        parameters: parameters,
        canTransferArrayBuffer: canTransferArrayBuffer,
      },
      transferableObjects
    ;

    return deferred.promise;
  };
};
createWorker(函数为

function createWorker(processor {
  const worker = new Worker(getBootstrapperUrl(;
  worker.postMessage = defaultValue(
    worker.webkitPostMessage,
    worker.postMessage
  ;
  // ...
  return worker;
}

不难看出,Cesium中将Web Workers封装成了Promise,既有操作Promise的优雅,又有调用Web Workers带来的多线程优势

Scene\Primitive.js中,使用TaskProcessor创建Geometry

createGeometry.js的文件名创建TaskProcessor

if (!defined(createGeometryTaskProcessors {
    createGeometryTaskProcessors = new Array(numberOfCreationWorkers;
    for (i = 0; i < numberOfCreationWorkers; i++ {
        createGeometryTaskProcessors[i] = new TaskProcessor("createGeometry";
    }
}

然后创建promise数组:

promises.push(
    createGeometryTaskProcessors[i].scheduleTask(
        {
            subTasks: subTasks[i],
        },
        subTaskTransferableObjects
    
;

最后使用Promise.all方法执行所有任务并等待结果返回:

Promise.all(promises
    .then(function (results {
    primitive._createGeometryResults = results;
    primitive._state = PrimitiveState.CREATED;
}
    .catch(function (error {
    setReady(primitive, frameState, PrimitiveState.FAILED, error;
};

4. 参考资料

[1] Web Workers API - Web API 接口参考 | MDN (mozilla.org

[3] Cesium原理篇:4Web Workers剖析 - fu*k - 博客园 (cnblogs.com

[5] Web Worker 之全面讲解 - 知乎 (zhihu.com

[6] 使用 Service Worker - Web API 接口参考 | MDN (mozilla.org

编程笔记 » Cesium之Web Workers

赞同 (27) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽