1.什么是 web Worker
构造函数 可以供主线程生成Worker线程
优缺点
- 优点
- 负担一些计算密集型或高延迟的任务,使主线程更流畅
- 缺点
- Worker线程一旦新建成功,就会始终运行,不会被主线程上的活动(用户点击按钮,提交表单等用户操作)打断。这样利于随时相应主线程的通信,但也造成了Worker比较耗费资源,不应该过度使用,一旦使用完毕,就应该关闭
使用场景
- 做一些大计算量的操作
- 可以实现轮询,改变某些状态
- 页头消息状态更新,比如页头的消息个数通知
- 高频用户交互,拼写检查,比如,根据用户的输入习惯、历史记录及缓存等信息来协助用户完成输入的纠错、矫正功能等
- 加密:需要经常加密很多数据的时候(发往服务器前加密数据)
- 预取数据:为了优化网站或者网络应用及提升数据加载时间
2. 为什么使用web Worker
为JavaScript创造多线程环境,允许主线程创建Worker线程,将一些任务分配给Worker线程运行。在主线程运行的同时,Worker线程在后台运行,互不干扰。等Worker线程完成计算任务,再把结果返回给主线程。
3.怎么使用web Worker
3.1 存在一个文件和一个本地服务器
index.html serve.js
3.2 创建文件夹,用来存放主线程和Worker线程
主线程 main.js
Workers线程 worker.js
main.js
//!!!!使用之前先判断是否支持Worker
if(window.Worker){
//1.创建一个worker线程
const myWorker = new Worker('src/worker.js')
//2.定义一个接收worker线程返回内容的方法
myWorker.onmessage = e => {
const message = e.data
document.getElementById('mess').innerHTML = message
}
//可以监听worker线程的错误
myWorker.onerror = error => {
//抛出异常
//throw error
//如果有错误就销毁worker线程
//主线程关闭Worker
myWorker.terminate()
}
//3.向worker线程发送消息,默认拷贝方式发送二进制数据,会造成性能问题
myWorker.postMessage('写的真好')
//规定发送的文件格式
myWorker.postMessage(arrayBuffer,[arrayBuffer])
}
worker.js
//造一个错误的,测试主线程的错误监听事件
alert('workers不能使用window对象下的默认方法')
//1.接收主线程发送消息
onmessage = e => {
const message = e.data
//2.对主线程发送的消息处理
if(message.indexOf('好') !== -1){
//3.返回对消息的处理
postMessage('谢谢')
}
//Worker线程关闭Worker
self.close()
}
使用说明
- onmessage事件处理函数的事件对象
- 异常监控
总结
- worker内,不能操作DOM节点,也不能使用window对象的默认方法和属性,,,但是可以使用window下的WebSockets|IndexedDB| FireFox OS专用的Data Store API等数据存储机制
- 主线程脚本文件和worker线程脚本文件必须在同一目录下(同源限制)
- worer线程不能读取本地文件,它加载的脚本,必须来自服务器(需要启动一个服务器serve.js文件)
- worker的最顶层对象不是window,而是WorkerGlobalScope
- worker和主线程间通过 postMessage发送消息,通过 onmessage事件处理函数来接收数据(事件对象e), 过程中数据是复制了而不是共享
4.API
4.1 主线程
实例化 Worker构造函数
var myWorker = new Worker(jsUrl,options)
//jsUrl : 脚本的路径(遵守同源限制)
//options: 指定Worker的名称,用来区分多个Worker线程
new Worker('worker.js',{name:'myWorker'})
Worker实例的属性和方法
- onerror: 监听Worker线程的错误
- onmessage: 监听Worker线程发送的数据 在Event.data中
- onmessageerror: 发送的数据无法序列号成字符串时触发
- postMessage() : 向Worker线程发送消息
- terminate(): 终止Worker线程
4.2 Worker线程
worker的最顶层对象不是window,而是WorkerGlobalScope
Worker线程的全局属性和方法(WorkerGlobalScope的属性和方法)
- self 属性: 用来获取对这个对象本身的引用(使用self表示WorkerGlobalScope)
- location属性: 线程的url相关信息
- close() : workers自身销毁(Worker线程)
- caches : 确保离线可用,同时可自定义请求的响应
- console:可以使用console语句
- importScripts(): 通过url在worker中加载其他脚本(可加载多个),实现文件动态加载
- XMLHttpRequest : 发送Ajax请求
- setTimeout|setInterval|addEventListener|postMessage
5.web Worker分类
5.1 专用线程 Worker对象
只能被创建它的主线程使用
5.2 共享线程 SharedWorker对象
可以被多个主线程使用
6.实例
6.1 专用线程:计时效果
main.js
//前提:index.html里有个按钮,控制什么时候开启Worker线程计时
document.querySelector('.btn').onclick=function(){
const worker = new Worker('src/worker.js')
worker.onmessage = e => {
//查看计时效果
console.log(e.data)
}
//每隔一秒发送将当前时间发送给主线程
worker.postMessage(1000)
}
worker.js
self.onmessage = e => {
let nowDate = new Date()
let currentDate = null
do{
currentDate = new Date()
}while(nowDate - currentDate > e.data)
self.postMessage(currentDate)
}
nowDate = new Date()
let currentDate = null
do{
currentDate = new Date()
}while(nowDate - currentDate > e.data)
self.postMessage(currentDate)
}