现代浏览器为JavaScript创造的 多线程环境。可以新建并将部分任务分配到worker线程并行运行,两个线程可 独立运行,互不干扰,可通过自带的 消息机制 相互通信。
基本用法:
// 创建 worker
const worker = new Worker('work.js');
// 向 worker 线程推送消息
worker.postMessage('Hello World');
// 监听 worker 线程发送过来的消息
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
}
复制代码
限制:
- 同源限制
- 无法使用
document/window/alert/confirm - 无法加载本地资源
当我们有些任务需要花费大量的时间,进行复杂的运算,就会导致页面卡死:用户点击页面需要很长的时间才能响应,因为前面的任务还未完成,后面的任务只能排队等待。对用户来说,这样的体验无疑是糟糕的,web worker 就是为了解决这种花费大量时间的复杂运算而诞生的!
WebWorker 的作用:创建 worker 线程
WebWorker 允许在主线程之外再创建一个 worker 线程,在主线程执行任务的同时,worker 线程也可以在后台执行它自己的任务,互不干扰。
这样就让 JS 变成多线程的环境了,我们可以把高延迟、花费大量时间的运算,分给 worker 线程,最后再把结果返回给主线程就可以了,因为时间花费多的任务被 web worker 承担了,主线程就会很流畅了!
Web Worker的出现,给浏览器带来了后台计算的能力,把耗时的任务分配给worker线程来做,在很大程度上缓解了主线程UI渲染阻塞的问题,提升页面性能。
1. 主线程与 worker 线程通信:
worker.postMessage({
hello: ['hello', 'world']
});
2.监听 worker 线程返回的信息
worker.onmessage = function (e) {
console.log('父进程接收的数据:', e.data);
// doSomething();
}
3. 主线程关闭 worker 线程
Worker 线程一旦新建成功,就会始终运行,这样有利于随时响应主线程的通信。
这也是 Worker 比较耗费计算机的计算资源(CPU)的原因,一旦使用完毕,就应该关闭 worker 线程。
worker.terminate(); // 主线程关闭worker线程
4. 监听错误
// worker线程报错
worker.onerror = e => {
// e.filename - 发生错误的脚本文件名;e.lineno - 出现错误的行号;以及 e.message - 可读性良好的错误消息
console.log('onerror', e);
};
self 代表 worker 进程自身
worker 线程的执行上下文是一个叫做WorkerGlobalScope的东西跟主线程的上下文(window)不一样。
我们可以使用self/WorkerGlobalScope来访问全局对象。
监听主线程传过来的信息:
self.onmessage = e => {
console.log('主线程传来的信息:', e.data);
// do something
};
复制代码
发送信息给主线程
self.postMessage({
hello: [ '这条信息', '来自worker线程' ]
});
复制代码
worker 线程关闭自身
self.close()
复制代码
worker 线程加载脚本:
Worker 线程能够访问一个全局函数 imprtScripts()来引入脚本,该函数接受 0 个或者多个 URI 作为参数。
importScripts('http~.js','http~2.js');
复制代码
- 脚本中的全局变量都能被 worker 线程使用。
- 脚本的下载顺序是不固定的,但执行时会按照传入 importScripts() 中的文件名顺序进行,这个过程是同步的。