PWA(Progressive Web App)入门系列:(五)Web Worker
前言
在说Service Worker前有必要说一下Web Worker,因为Service Worker本身就属于Web Worker的延伸,大部分功能也是基于Web Worker进行的扩展。
背景
众所周知,JavaScript引擎是以单线程调度的方式进行,我们无法同时运行多个JavaScript文件,这种情况下就会导致对硬件资源无法充分利用,并且当在进行一些高耗性能的操作时,会影响主线程的其他任务,造成任务阻塞及用户体验差等问题。
在这种劣势情况下,到 2008 年 W3C 提出第一个 HTML5 草案开始,就在 HTML5 中提出了Web Worker的概念,并规范了Web Worker的三大特征:
- 能够长时间运行
- 理想的启动性能
- 理想的内存消耗
简介
Web Worker 是HTML5标准的一部分,这一规范定义了一套 API。实现了 用Web Worker 来实现 JavaScript 的 “多线程” 技术,并发执行多个 JavaScript 脚本。
Web Worker 与传统多线程
每个JavaScript脚本执行流都称为一个线程,彼此之间互相独立,并且有浏览器中的 JavaScript 引擎负责管理,当然这并不是说JavaScript支持多线程,虽然传统JavaSript有多种方式实现了对多线程的模拟(例如:setinterval,setTimeout,以及一些异步的操作方法等),但是在本质上程序的运行仍然是由 JavaScript 引擎以单线程调度的方式运行的,而Web Worker的线程是依赖于浏览器(宿主环境)来实现的,从而实现了对浏览器端多线程编程的支持。
Web Worker 线程种类
Web Worker 有两种不同线程类型,分别是:
- Dedicated Worker (专用线程)。只能被首次生成它的脚本使用
- Shared Worker (共享线程)。可以同时被多个脚本使用
通常来说的Web Worker指的就是Dedicated Worker,Service Worker也属于其中,并且各大浏览器对其支持良好,而Shared Worker指的是SharedWorker,目前各大浏览器对其支持度较差。
这里主要对Dedicated Worker进行详细说明,对于Shared Worker不再进行细说。
Worker模式
Worker线程执行流
创建 Web Worker
下面说一下如何创建一个Web Worker
语法:
new Worker(in DOMString aStringURL
);
使用上面的方式即可以创建一个Web Worker对象,它执行的是aStringURL中的脚本。目前大多数浏览器是支持data URI的aStringURL的,可以通过URL.createObjectURL(blob)创建。但需要注意的是脚本必须遵循同源策略。
下面创建一个Worker,Worker的执行脚本是workerfile.js
,创建成功后,它会返回一个新的Worker对象赋值给前面声明的workerObj变量
var workerObj = new Worker('./workerfile.js');
这里需要注意, worker线程的创建的是异步的,主线程代码不会阻塞在这里去等待worker线程去加载、执行相应的脚本文件,而是会立即向下执行后面代码。
Web Worker实例方法
Worker的实例方法只有两个:
- postMessage
- terminate
postMessage
主线程向生成的Worker线程发送数据的方法。
语法:
workerObj.postMessage(aMessage, transferList);
- aMessage:向Worker线程发送的消息数据对象。它可以是任何类型的值或JavaScript对象。
- transferList:可选。Transferable类型的数组。主要用在 ArrayBuffer, MessagePort, ImageBitmap对象。
注意:
postMessage发送的aMessage参数,在传递通讯的时候会对数据进行克隆,为了防止多个线程间的数据同时修改的问题。实际上,浏览器内部的实现是,先将通信传递的数据串行化,随后把串行化后的数据发给子线程,后者再将数据还原。
postMessage也可以以二进制的方式传输,例如 ArrayBuffer 、File、Blob、ImageBitmap等对象。但是往往传输的这些对象数据量都很大,前面说了传输数据会进行拷贝,如果传一个100MB的数据,那么浏览器默认会再复制一份100MB的数据,导致一些不必要的资源消耗。为了防止这种问题,就可以使用上面说的第二个参数transferList来解决。
顺道科普一下Transferable接口。这个接口代表一个能在不同可执行上下文中相互传递的对象,例如主线程和Worker线程。
var arrBuff = new ArrayBuffer(8);
myWorker.postMessage(arrBuff, [arrBuff]);
terminate
语法:
workerObj.terminate()
用于立即终止worker对象的行为,如果worker正在运行着任务也会立即终止。
Web Worker实例属性
Worker实例包含两个属性:
- onmessage:用来接收worker线程传递过来的数据事件。
- onerror:用来接收worker线程的错误信息。
onmessage
onmessage属性表示一个EventHandler事件处理函数,当Worker子线程返回一条消息时被调用。
语法:
workerObj.onmessage = function(e) { ...
}
传递来的消息被封装在事件的data属性中。
workerObj.onmessage = function(e) {var result = e.data;
}
onerror
onerror属性是EventListener 一个事件监听函数,一旦有类型为 error 的 ErrorEvent 从 worker线程中冒泡出来时就会执行该函数。可以通过preventDefault()来取消冒泡。
主要用到的错误属性有:
- message: 可读的错误信息
- filename: 发生错误的脚本文件名称
- lineno: 发生错误的脚本所在文件的行数
Web Worker文件方法
Worker线程对象抽象于DedicatedWorkerGlobalScope接口。此作用域下没有window对象,需要用self来调用。
在发送数据和接收数据使用的方法和worker实例对象的一样:
- postMessage
- onerror
这两个方法就不说了,还有一个close方法说一下。
close
这个和terminate()有点类似。这个方法主要用来清除所有在WorkerGlobalScope事件环中的排队任务,关闭特定作用域。
self.close()
importScripts 导入脚本
WorkerGlobalScope 对象中可以使用importScripts()方法来进行对脚本文件和资源的引入。
但这个操作需要注意:
- 如果没有给 importScripts 方法任何参数,那么立即返回,终止下面的步骤。
- 解析 importScripts 方法的每一个参数。
- 如果有任何失败或者错误,抛出 SYNTAX_ERR 异常。
- 尝试从用户提供的 URL 资源位置处获取脚本资源。
- 对于 importScripts 方法的每一个参数,按照用户的提供顺序,获取脚本资源后继续进行其它操作。
Worker线程声明周期
worker线程间的数据传递必须依赖于浏览器的context环境,通过MessagePort进行传递数据,所以每个worker线程的全局作用域都会有端口列表,并且会在WorkerGlobalScope中生成一个worker线程的线程列表,在初始化时为空。当worker线程创建时会被填充进去,当worker线程终止时会从这个列表删除。
worker线程中可调用的对象
在worker线程中,可以获得下列对象:
- navigator
- location
- XMLHttpRequest
- setTimeout/setInterval
- Application Cache
- fetch
- atob/btoa
等等。
实例
下面写一个使用的小例子
html文件:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body>
<button id="btn">发送</button>
<script>var worker = new Worker('./worker.js')btn.onclick = function(){worker.postMessage({a:1,b:2,c:3})}worker.onmessage = function(e){console.log('index-msg:', e)}worker.onerror = function(e) {console.log('index-err', e)e.preventDefault()}
</script>
</body>
</html>
worker.js文件
self.onmessage = function(e) {console.log('worker in:', e)self.postMessage('get postMessage!')
}
兼容性
还是有必要列一下Worker目前在浏览器上的兼容性:
可以看到支持的非常不错。
总结
可以看到Web Worker的出现使得在 Web 进行多线程编程成为可能,对于高消耗、耗时长的操作可以放到woker里面去进行。
所以可以在以下应用场景使用:
- 使用专用线程进行数学运算
- 图像处理
- 大量数据的检索
- 背景数据分析
等。
博客名称:王乐平博客
CSDN博客地址:http://blog.csdn.net/lecepin
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。
PWA(Progressive Web App)入门系列:(五)Web Worker相关推荐
- PWA(Progressive Web App)入门系列:(一)PWA简介
前言 PWA做为一门Google推出的WEB端的新技术,好处不言而喻,但目前对于相关方面的知识不是很丰富,这里我推出一下这方面的入门教程系列,提供PWA方面学习. 什么是PWA PWA全称Progre ...
- PWA(Progressive Web App)入门系列:(三)PWA关键技术Manifest
前言 前面说过,让Web App能够达到Native App外观体验的主要实现技术就是PWA中的manifest技术,本章会详细说明manifest的实现,及各个参数的具体含义,还将了解如何定义Web ...
- PWA(Progressive Web App)入门系列:安装 Web 应用
前言 在传统的 Web 应用中,通常只能通过在浏览器的地址栏里输入相应的网址才能进行访问,或者把网页地址创建到桌面上通过点击,然后在浏览器里打开. 传统模式下,图标.启动画面.主题色.视图模式.屏幕方 ...
- PWA(Progressive Web App)入门系列:Sync 后台同步
前言 当我们在一些地下停车场,或者在火车上.电梯等无法避免的信号不稳定的场所,使用网站应用处理一些表单操作或者上传数据的操作时,面临的将是网络连接错误的响应,使用户的操作白费. 而此刻 PWA 的 S ...
- PWA(Progressive Web App)入门系列:Cache Storage Cache
前言 目前浏览器的存储机制有很多,如:indexedDB.localStorage.sessionStorage.File System API.applicationCache 等等,那为什么又制定 ...
- PWA(Progressive Web App)入门系列:(二)相关准备
前言 在上一章中,对PWA的相关概念做了基本介绍,了解了PWA的组成及优势.为了能够更快的进入PWA的世界,这一章主要对在PWA开发中,需要注意的问题,运行的环境及调试工具做介绍说明. 浏览器要求 因 ...
- PWA(Progressive Web App)入门系列:Push
前言 很多时候,原生应用会通过一些消息推送来唤起用户的关注,增加驻留率.网页该怎么做呢?有没有类似原生应用的推送机制?推送功能又能玩出什么花样呢? Push API Push API 给与了 Web ...
- PWA(Progressive Web App)入门系列:Notification
前言 在很多场景下,需要一种通知的交互方式来提醒用户,传统方式下可以在页面实现一个 Dialog,或通过修改网页的 title 来实现消息的通知.然而传统的实现存在着一定的不足,在网页最小化的情况下, ...
- PWA(Progressive Web App)入门系列:Fetch Request Headers Response Body
前言 在 WEB 中,对于网络请求一直使用的是 XMLHttpRequest API 来处理,XMLHttpRequest 也很强大,传统的 Ajax 也是基于此 API 的.那么为什么 W3C 标准 ...
最新文章
- win 2008 控制共享文件夹大小_Windows转Mac Win10局域网文件共享设置
- python多线程队列爬虫流程图_python 多线程爬虫 队列queue问题。
- 04,认证、权限、频率
- java super extends_Java继承和super的用法
- 一个成型的awt所必须的frame组件
- testlink配置修改
- css中hack是什么
- 12步让你的web1.0变成web2.0
- jQuery 5 条件选择器
- 安卓装Linux ,坑真的多,Linux deployTermux踩坑记||在旧手机上建立自己的服务器(1)||2020年新货
- DAVIS2016+Matlab+Win10使用指南
- 华为鸿蒙主机,华为发布全屋智能主机以及V系列智慧屏 搭载鸿蒙系统
- word中“项目符号”和后面的文字间隔太远
- java中的消息提示框
- Error starting userland proxy: listen tcp4 0.0.0.0:8005: bind: address alrea
- Open3D 曲面重建
- 产品全类目下找不到关键词,只有到特定类目才能找到,修改PRODUCT TYPE
- new和delete,malloc和free
- js将数字转换成大写汉字
- 数据软件分析(一)——静态分析
热门文章
- 解释spring,struts,hibernate优缺点
- 团队作业-第二周-测试计划
- 主流平台应用与游戏的编程语言/工具(图)
- 18款 非常实用 jquery幻灯片图片切换
- 2013年3月16日星期六
- 听小鹏讲废话之OSI
- ExtJs UI框架学习六
- css+沿正方形旋转,CSS3+SVG+JS 正方形沿着正方本中轴移动翻转的动画
- spark的流失计算模型_使用spark对sparkify的流失预测
- spring中@Inject和@Autowired的区别?分别在什么条件下使用呢?