10月阅读周·JavaScript异步编程设计快速响应的网络应用:网页版worker对象

举报
叶一一 发表于 2024/10/22 09:45:26 2024/10/22
【摘要】 背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读九个月。已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScri...

背景

去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。

没有计划的阅读,收效甚微。

新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。

这个“玩法”虽然常见且板正,但是有效,已经坚持阅读九个月。

已读完书籍《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》、《JavaScript权威指南》

当前阅读周书籍《JavaScript异步编程设计快速响应的网络应用》

网页版worker对象

网页版 worker对象是大名鼎鼎的 HTML5标准的一部分。要想生成worker对象,只需以脚本 URL为参数来调用全局 Worker 构造函数即可。

var worker = new Worker('worker.js');
worker.addEventListener('message', function (e) {
  console.log(e.data); // 重复由postMessage 发送的任何东西
});

(通常,我们只用到message事件的data属性。如果已经把同一个事件处理器绑定至多个worker对象,则可能还要用到e.target以定位是哪一个worker对象触发了事件。)

现在我们知道如何监听worker对象了。worker对象的交互接口呈现出便利的对称设计:我们可以使用worker.postMessage来发送消息,而 worker本身可以使用 self.addEventListener('message',……)来接收消息。下面是一个完整的例子。

// 主脚本
var worker = new Worker('boknows.js');
worker.addEventListener('message', function (e) {
  console.log(e.data);
});
worker.postMessage('football');
worker.postMessage('baseball');
// boknows.js
self.addEventListener('message', function (e) {
  self.postMessage('Bo knows ' + e.data);
});

大家可以在笔者创建的一个小网站上(Web Worker Sandbox)“把玩”worker 对象的这种消息传递接。创建一个新例子之后,你会得到一个可与他人分享的唯一URL地址。

网页版worker对象的局限性

网页版worker对象的首要目标是,在不损害DOM响应能力的前提下处理复杂的计算。它有以下几种潜在用法:

  • 解码视频。流入的视频采用Broadway实现的H.264编解码器
  • 采用斯坦福的JavaScript加密库加密通信
  • 解析网页式编辑器中的文本。没错,就是Ace编辑器

事实上,Ace默认已经这么做了。在基于Ace的编辑器中键入代码时,Ace需要先进行一些相当繁重的字符串分析,然后再使用恰当的语法高亮格式更新 DOM。在现代浏览器中,这种分析工作通常会另开一个独立线程来做,以确保编辑器能保持平滑度和响应度。

通常情况下,worker对象会把自己的计算结果发送给主线程,由主线程去更新页面。为什么不直接更新页面呢?这主要是为了保护JavaScript异步抽象概念,使其免受影响。如果worker对象可以改变页面的标记语言,那么最终的下场就会和Java一样——必须将DOM操控代码封装成互斥量和信号量以避免竞态条件。

基于类似的理由,worker对象也看不到全局的window对象和主线程及其他worker线程中的其他任何对象。通过postMessage发送的对象会透明地作序列化和反序列化,想想 JSON.parse(JSON.stringify(obj))吧。因此,原始对象的变化不会影响该对象在其他线程中的副本。

worker对象甚至不能使用老实可靠的 console 对象。它只能看到自己的全局对象self,以及self已捆绑的所有东西:标准的JavaScript对象(如setTimeout和Math),以及浏览器的Ajax方法。

对了,还有Ajax!worker对象可以随意使用XMLHttpRequest。如果浏览器端支持的话,它甚至能使用 WebSocket。这意味着 worker可以直接从服务器拉取数据。如果要处理大量数据(譬如说,流传输一段需要解码的视频),相比于使用postMessage来序列化这些数据,将数据封闭在一个线程中会更好。

还有一个特殊的importScripts函数可以同步地加载并运行指定的脚本。

importScripts('https://raw.github.com/gist/1962739/danika.js');

总结

正常情况下,同步加载是绝对禁忌,不过 worker 对象跑的是另一个线程。既然worker已经无所事事了,那么阻塞就阻塞好啦!


作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏️ | 留言📝

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。