HTML5多线程Web Worker

309 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

JavaScript是单线程语言, 同一时刻只能做一件事情, 并且执行JS时Html渲染引擎会进入阻塞状态,得等到JS执行完成后才能继续进行Html页面渲染,我们开发中也会遇到此类问题,当JS中大量的计算或者其他情况,需要耗时一段时间,页面有时只会渲染一部分或者白屏得等上一会。这时候我们可以根据情况可以选择使用Web Worker,html5提供的一个允许javascript创建多个线程的标准,它可以在后台进行运行,不会影响或阻塞主线程的运行,但是Web Worker有一些限制,我们要根据我们的情况并考虑这些限制进行选择是否使用Web Worker来实现一些需要耗时的功能。

1.你不能操纵DOM元素。
2.不能使用window对象中的某些方法和属性,如alert、confirm等。
3.webworker脚本文集必须和主线程JS脚本是同源的,不能加载客户端本地脚本。
4.webworker和主线程JS脚本之间不能直接调用得通过消息传递,传递的内容必须可以序列化,比如函数等就不能传递。

使用

主线程
通过实例化worker创建worker对象,参数为web worker子线程js文件地址,必须和当前是同源文件,通过 onmessage和postMessage和子线程进行数据交互。可以通过onerror监听子线程错误。

const worker = new Worker('/calc.worker.js');
// 接受web worker子线程发送过来的数据
worker.onmessage = (event) => {
  console.log('接收子线程数据:', event.data); // hello 小明
  // 可以在子线程处理完成任务后关掉web worker子线程
  worker.terminate();
};
// 向web worker子线程发送数据
worker.postMessage({ name: '小明' });
// 主线程可以监听子线程是否发生错误。如果发生错误,web worker会触发主线程的error事件。
worker.onerror((e) => {
  console.log(e.message);
});

web worker子线程
通过onmessage和postMessage和主线程进行消息传递,子线程中也可以加载js脚本通过importScripts方法进行加载。

// 接收主线程发送的数据
self.onmessage = function(event) {
  console.log(event.data); // { name: '小明' }
  calc(event.data);
};

function calc(data) {
  // 向主线程发送数据
  postMessage(`hello ${data.name}`);
  // 关掉当前线程
  self.close();
}

importScripts('/test.js', 'test1.js')