web worker

155 阅读3分钟

现代浏览器为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');
复制代码
  1. 脚本中的全局变量都能被 worker 线程使用。
  2. 脚本的下载顺序是不固定的,但执行时会按照传入 importScripts() 中的文件名顺序进行,这个过程是同步的。