初探 HTML5 Web Workers

原文:初探 HTML5 Web Workers

一、Web Workers是什么

Web Worker为Web内容在后台线程中运行脚本提供了一种简单的方法。线程可以执行任务而不干扰用户界面。此外,他们可以使用XMLHttpRequest执行 I/O (尽管responseXML和通道属性总是为空)。一旦创建, 一个worker 可以将消息发送到创建它的JavaScript代码, 通过将消息发布到该代码指定的事件处理程序 (反之亦然)。 —— MDN

众所周知,JavaScript是单线程的编程语言,也就是说,当我们在页面中进行一个较为耗时的计算的JavaScript代码时,在这段代码执行完毕之前,页面是无法响应用户操作的。也正是出于这个原因,HTML5为我们提供了 Web Workers 以解决这种问题,当我们需要在JavaScript中来进行耗时的计算或诸如此类的问题时,我们可以使用 Web Workers 在浏览器的后台启动一个独里的 Worker 线程来专门负责这段代码的运行,而不会阻碍后面代码的运行。

二、Web Workers的使用

1. 实例化一个 Worker

实例化运行一个 Worker 很简单,我们只需要 new 一个 Worker 全局对象即可。

var worker = new Worker('./worker.js')

它接受一个 filepathname String 参数,用于指定 Worker 脚本文件的路径。然后我们就可以在 worker.js 中写下一些代码:

console.log('my_WOEKER:', 'srtian')

另外,通过URL.createObjectURL()创建URL对象,也可以实现创建内嵌的worker:

var myTask = `
    var i = 0;
    var timedCount = () => {
        i = i+1;
        postMessage(i);
        setTimeout(timedCount, 1000);
    }
    timedCount();
`;

var myblob = new Blob([myTask]);
var myWorker = new Worker(window.URL.createObjectURL(myblob));

需要注意的是,传入 Worker 构造函数的参数 URI 必须遵循同源策略。

此外因为Worker线程的创建的是异步的,所以主线程代码不会阻塞在这里等待 worker 线程去加载、执行指定的脚本文件,而是会立即向下继续执行后面代码这点也需要注意。

2. 数据通信

当我们实例化一个 Worker 线程后,Worker不会相互,或者与主程序共享任何作用域或资源——那会将所有的多线程编程的噩梦带到我们面前——取而代之的是一种连接它们的基本事件消息机制。因此他们需要通过基于事件监听机制的message来进行通信,我们在new Worker()后悔返回一个实例对象,它包含了一个postMessage的方法,我们可以通过调用这个方法来给worker线程传递信息,我们也可以给这个对象监听事件,从而在worker线程中出发事件通信的时候能接收到数据。

var worker = new worker('./worker.js')
worker.addEventListener('message', function(e) {
    console.log('worker receive:', e.data )
}
worker.postMessage('hello worker,this is main.js')

然后在worker.js这个脚本中,我们就可以调用全局函数postMessage和全局的onmessage赋值来发送和监听数据和事件了。

// 监听事件
onmessage = function (e) {
  console.log('WORKER RECEIVE:', e.data);
  // 发送数据事件
  postMessage('Hello, this is worker.js');
}

需要注意的是 worker 支持 JavaScript 中所有类型的数据传递,可以传递一个 Object 数据;但这里的数据传递(主要是 Object 类型)并不是共享,而是复制。发送端的数据和接收端的数据是复制而来,并不指向同一个对象,此外这里的复制不是简单的拷贝,而是通过两端的序列化/解序列化来实现的,一般来说浏览器会通过 JSON 编码/解码;当然,这里的更多细节部分会由浏览器来处理,我们并不需要关心这些,只需要明白两端的数据是复制而来,互相独立的就行了。

3. 错误处理机制

当 worker 出现运行中错误时,它的 onerror 事件处理函数会被调用。它会收到一个扩展了 ErrorEvent 接口的名为 error的事件。

该事件不会冒泡并且可以被取消;为了防止触发默认动作,worker 可以调用错误事件的 preventDefault() 方法。

错误事件有以下三个用户关心的字段:

  • message: 可读性良好的错误消息。
  • filename: 发生错误的脚本文件名。
  • lineno: 发生错误时所在脚本文件的行号。

实际操作如下:

var worker = new Worker('./worker.js');

// 监听消息事件
worker.addEventListener('message', function (e) {
  console.log('MAIN RECEIVE: ', e.data);
});
// 也可以使用 onMessage 来监听事件:


// 监听 error 事件
worker.addEventListener('error', function (e) {
  console.log('MAIN ERROR:', e);
  console.log('MAIN ERROR:', 'filename:' + e.filename + '---message:' + e.message + '---lineno:' + e.lineno);
});


// 触发事件,传递信息给 Worker
worker.postMessage({
  m: 'Hello Worker, this is main.js'
});

4. 终止 Worker

当我们在不需要 Worker 继续运行时,我就需要终止掉这个线程,这时候我们就可以调用 worker 的 terminate 方法:

worker.terminate()

worker 线程会被立即杀死,不会有任何机会让它完成自己的操作或清理工作。

而在worker线程中,workers 也可以调用自己的 close 方法进行关闭:

close()

三. Web Workers的兼容

由于Web Workers是HTML5所提供的,因此从兼容性上来说,还是需要注意的。总的兼容情况如下图所示:

image

图片来源:https://caniuse.com/#feat=webworkers

我们可以看到,虽然web worker很不错,但如果我们的代码执行在较老的浏览器中时,是缺乏支持的。但由于worker是一个API而不是语法,因此我门还是可以去填补它的。

这一块的详情可以去看——《你不知道的JavaScript中卷》关于 web worker 的那一节。

四、Web Workers支持的JavaScript特性

由于在 Worker 线程的运行环境中没有 window 全局对象,也无法访问 DOM 对象,所以一般来说我们在这只能执行纯JavaScript的计算操作,当然1我们那:

  • setTimeout(), clearTimeout(), setInterval(), clearInterval():有了设计个函数,就可以在 Worker 线程中执行定时操作了;
  • XMLHttpRequest 对象:意味着我们可以在 Worker 线程中执行 ajax 请求;
  • navigator 对象:可以获取到 ppName,appVersion,platform,userAgent 等信息;
  • location 对象(只读):可以获取到有关当前 URL 的信息;
  • 应用缓存
  • 使用 importScripts() 引入外部 script
  • 创建其他的 Web Worker

五、Web Worker 的实践

总的来说,Web Worker为我们带来了强大的计算能力,我们可以加载一个JavaScript进行大量的复杂计算,而用不挂起主进程。并通过postMessage,onmessage进行通信,这也解决了大量计算对UI渲染的阻塞问题。

应用场景

1、数学运算

Web Worker最简单的应用应该就是用来进行后台计算了,这对CPU密集型的场景再适合不过了。

2、图像处理

通过使用从 canvas 中获取的数据,可以把图像分割成几个不同的区域并且把它们推送给并行的不同Workers来做计算,对图像进行像素级的处理,再把处理完成的图像数据返回给主页面。

3、大数据的处理

目前mvvm框架越来越普及,基于数据驱动的开发模式也越愈发流行,未来大数据的处理也可能转向到前台,因此我们将大数据的处理交给在Web Worker也是很好的。

4. 数据预处理

为优化的网站或 web 应用的数据加载时长,我们可以使用 Web Worker 预先获取一些数据,存储起来以备后续使用,因为它绝不会影响应用的 UI 体验。

5. 大量的 ajax 请求或者网络服务轮询

由于在主线程中每启动一个XMLHttpRequest请求都会消耗资源,虽然在请求过程中浏览器另外开了一个线程,但是在交互过程中还是需要消耗主线程资源;而使用worker则不会过多占用主线程,只是启动worker过程时比较耗资源。

参考资料:

  1. 《你不知道的JavaScript中卷》
  2. https://juejin.im/post/59c1b3645188250ea1502e46
  3. https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers
  4. https://qiutc.me/post/the-multithread-in-javascript-web-worker.html
  5. https://juejin.im/post/5a90233bf265da4e92683de3
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容

  •   随着 HTML5 的出现,面向未来 Web 应用的 JavaScript API 也得到了极大的发展。这些 A...
    霜天晓阅读 1,025评论 0 0
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,360评论 8 265
  • 第一章 补习班的初遇 在一座别墅区里,有一个独特的别墅,那座别墅除了窗户,全都是白色的。 ...
    陳敐阅读 311评论 0 2
  • 以前从未接触过,但最近迫切地想了解有关《红高粱》的故事,我是急于求成的,直奔着电影去了。 在我的生活中,一切似乎都...
    心里有很多事阅读 211评论 0 1
  • 本文参加#印象青农,萌有感受#活动,本文承诺,文章内容为原创,且未在其他平台发表过。 时光荏苒,一转眼我们走...
    井宝1阅读 331评论 0 0