专栏首页Young Dreamerweb worker 扫盲篇

web worker 扫盲篇

什么是woker

官方的解释是这样的:

worker是一个对象,通过构造函数Worker创建,参数就是一个js文件的路径;文件中的js代码将运行在主线程之外的worker线程;

var jsFileURI = JS_FILE_PATH;  // js文件路径

var worker = new Worker(jsFileURI);

worker运行在另一个全局上下文中(self),这个全局上下文不同于window,所以不能在woker中访问window和DOM;

该线程分为两种:dedicated workershared worker;dedicated worker只能被初始化它的js上下文中使用;shared worker可以在多个js上下文中使用。通常使用的worker是dedicated worker,它的工作情况可以通过chrome的调试工具查看。

为什么引入woker?

前端开发者应该知道浏览器中JS和UI公用一个线程,JS计算过程中,不能响应UI;如果遇到计算量比较大的任务,如操作图像像素时,会造成用户行为得不到响应。Web Worker 是为了解决 JavaScript 在浏览器环境中没有多线程的问题。支持 Web Worker 的浏览器会额外提供一个 JavaScript Runtime 供 Web Worker 使用。它的最佳使用场景是执行一些开销较大的数据处理或计算任务。

woker是怎么工作的?

Web Worker 使用起来非常简单,在“主线程”中执行如下操作即可创建一个 Worker 实例,通过监听 onmessage 事件获取消息,通过 postMessage 发送消息:

“主线程”和Worker 之间通过 postMessage 发送消息,通过监听 onmessage 事件来接收消息,从而实现二者的通信。

如下图所示:

核心代码如下:

主线程中代码

var worker = new Worker('worker.js');
worker.onmessage = function (e) {
    var data = e.data;
}
var messageData = {
    message: 'hello worker!'
};
worker.postMessage(messageData);

worker.js 中的代码如下:

self.onmessage = function(e) {
    var messages = e.data;  // e.data为{message: 'hello worker!'}
    var workerResult = {};
    // do something
    ...
    postMessage(workerResult);
}

使用woker的几个tips

(1)使用多少个worker?

遇到复杂的计算,需要开启多少worker才合适呢?一般的做法是参考navigator.hardwareConcurrency 这个属性,它表示机器支持的并行最大任务数。还有一种动态检测 Worker 数量的方法,有兴趣的话可以看:https://github.com/oftn-oswg/core-estimator。

(2)优化woker与主线程通信开销

该段主要参考百度地图技术博客(https://mp.weixin.qq.com/mp/getmasssendmsg?__biz=MzIzNDE0NjMzOQ==#wechat_webview_type=1&wechat_redirect)。

Worker 与“主线程”之间的数据传递默认是通过结构化克隆(Structured Clone)完成的。数据量较大时,克隆过程会比较耗时,这会影响 postMessage 和 onmessage 函数的执行时间。

解决的办法一是先通过 JSON.stringify 将对象序列化,接收之后再用 JSON.parse 还原。因为:stringfiy + 传递字符串的耗时 < 传递对象的耗时 。

代码如下:

// 操作像素
    var imageData = context.createImageData(img.width, img.height);
    var work = new Worker('./cal.js');
    var data = {
        data: imageData.data,
        width: imageData.width,
        height: imageData.height
    };
    // 将传递的参数转换成字符串
    work.postMessage(JSON.stringify(data));

还有一种避开克隆传值的方法,就是使用Transferable Objects,主要是采用二进制的存储方式,采用地址引用,解决数据交换的实时性问题;Transferable Objects支持的常用数据类型有ArrayBuffer和ImageBitmap;

使用方法如下:

   // 操作像素
    var imageData = context.createImageData(img.width, img.height);
    var work = new Worker('./cal.js');
    // 转化为类型数组进行传递
    var int8s = new Int8Array(imageData.data);
    var data = {
        data: int8s,
        width: imageData.width,
        height: imageData.height
    };
    // 在postMessage方法的第二个参数中指定transferList
    work.postMessage(data, [data.data.buffer]);

经测试,使用arrayBuffer之后,传递数据所需的时间为1ms,极大地提高了数据传输的效率。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 简易前端模板引擎

    模板解析 解决的问题: 将data和js+html片段解析成html片段,完成赋值和js逻辑,如下所示: 输入: var data = {     name: ...

    用户1217459
  • VUE中的v-if与v-show

    1.共同点 都是动态显示DOM元素 2.区别 (1)手段:v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样...

    用户1217459
  • 前端页面统计beacon调研

    注意xhr.open('post', '/log', false)的第三个参数, false为同步请求,也就是document unload之前必须等待请求发...

    用户1217459
  • 模拟返回的后台数据实现统计图

    ProsperLee
  • jquery add element in the html dom

    pydata
  • 一步一步学Vue(八)

    Jerremy
  • HTML5+CSS3 做一个灵动的动画 TAB 切换效果

    HTML5+CSS3 做一个灵动的动画 TAB 切换效果 设计师给了一个 tab 切换的效果图。虽然是一个很小的功能,但是前端工程师在实现的时候还是有很多细节需...

    FungLeo
  • 主流无人机的核心技术对比:谁能挑战大疆的霸主地位?

    放眼科技和摄影界,时下或许没有比航拍无人机更为蓬勃发展的产业了。一众厂商不断推陈出新,教消费者挑花了眼。随着竞争的愈发激烈,厂商们纷纷不断提升自己的研发实力,也...

    机器人网
  • Ubuntu cron日志开启与查看的实现步骤

    默认cron会发送邮件把任务的运行结果比如错误信息发送到系统用户的邮箱中,而不会在log中出现具体的脚本运行输出的信息,所以我们可以指定一下每个任务的输出日志路...

    砸漏
  • bootstrap 下拉菜单 禁用菜单项

     <div class="dropdown"> <button type="button" class="btn btn-default dropdown-t...

    用户5760343

扫码关注云+社区

领取腾讯云代金券