探秘 Web Workers:JS也能玩多线程

54 阅读6分钟

在日常编码中,我们常常会面临这样的场景:一边要处理用户在网页上的各种操作,像点击按钮、输入文本;此时另一边,又有大量复杂的数据需要计算或者处理。这就好比我们要同时兼顾两个重要的会议,忙得不可开交。而 Web Workers 就像是我们可靠的 “代码搭档”,玩起多线程,帮我们分担一部分工作,让我们的代码运行得更加顺畅。

什么是 Web Workers

Web Workers 是 HTML5 里一项超棒的功能。它允许我们在浏览器里创建一个独立于主线程的后台线程。主线程就像是公司的 CEO,要负责统筹全局,处理用户的交互、页面的渲染等核心事务;而 Web Workers 则像是公司里的专业技术人员,在后台专注地完成一些复杂的计算或者数据处理任务,而且不会干扰到 CEO 的工作。

用在什么地方

处理复杂计算任务

假设你正在开发一个金融分析网页,需要对大量的股票交易数据进行复杂的统计和计算,比如计算股票的移动平均线。这是一个非常耗时的操作,如果在主线程中进行,就会导致页面卡顿,用户体验变差。这时候,Web Workers 就可以派上用场了。

进行文件解析

当你开发一个文件上传和解析的功能时,比如解析大型的 JSON 文件。解析这样的文件可能需要花费大量的时间和资源,如果在主线程中进行,会让用户长时间等待,感觉页面好像死机了一样。Web Workers 可以在后台独立地进行文件解析工作,主线程可以继续处理其他任务,比如显示进度条、提示用户等待等。

实现实时数据更新

在开发一些实时数据展示的应用时,比如实时天气查询应用。需要不断地从服务器获取数据并更新页面。如果每次获取数据和更新页面都在主线程中进行,会给主线程带来很大的压力,导致页面响应变慢。Web Workers 可以在后台定时从服务器获取数据,进行简单的处理后,再把更新后的数据传递给主线程,由主线程负责更新页面。

为什么需要 Web Workers

避免阻塞主线程

在浏览器中,主线程是非常忙碌的,它不仅要处理用户的交互事件,还要负责页面的渲染和更新。如果在主线程中执行一些耗时的任务,就会像在繁忙的交通要道上设置了一个路障,导致交通堵塞。Web Workers 的出现,就像是开辟了一条新的道路,让那些耗时的任务可以在这条道路上独立运行,不会影响主线程的正常工作,从而保证了页面的流畅性和响应速度。

提高性能

现代计算机通常都具有多个 CPU 核心,而主线程是单线程执行的,无法充分利用多核 CPU 的优势。Web Workers 可以在不同的线程中并行执行任务,就像多个同事同时为你完成不同的工作,这样可以充分利用多核 CPU 的计算能力,提高整体的性能。

优化用户体验

用户对于网页的响应速度和流畅性非常敏感。如果网页在处理复杂任务时出现卡顿,用户很可能会选择离开。Web Workers 可以让网页在处理复杂任务时依然保持流畅,用户可以在等待任务完成的同时继续进行其他操作,不会感到任何卡顿或者延迟。这样,用户就会对网页有更好的体验,更愿意使用你的应用。

JavaScript 操作示例

下面通过一个简单的 JavaScript 示例,来看看 Web Workers 是如何工作的。

主线程代码(main.js)

// 创建一个新的 Web Worker,指定 worker.js 作为工作线程的代码文件
const worker = new Worker('worker.js');

// 向工作线程发送消息,这里发送了一个数字 10
worker.postMessage(10);

// 监听工作线程返回的消息
worker.onmessage = function (event) {
    // 当收到工作线程的消息时,将消息中的数据打印到控制台
    console.log('接收到工作线程的结果: ', event.data);
};

// 监听工作线程的错误信息
worker.onerror = function (error) {
    // 当工作线程发生错误时,将错误信息打印到控制台
    console.error('工作线程发生错误: ', error.message);
};

工作线程代码(worker.js)

// 监听主线程发送的消息
self.onmessage = function (event) {
    // 获取主线程发送过来的数据
    const number = event.data;
    // 进行简单的计算,这里将接收到的数字进行平方运算
    const result = number * number;
    // 将计算结果返回给主线程
    self.postMessage(result);
};

代码解释

  • 主线程(main.js)

    • new Worker('worker.js'):这行代码创建了一个新的 Web Worker 实例,指定 worker.js 作为工作线程的代码文件。就像是你雇佣了一个新的同事,并告诉他去哪个办公室(代码文件)工作。
    • worker.postMessage(10):通过 postMessage 方法向工作线程发送消息,这里发送了一个数字 10。这就好比你给同事发了一封邮件,告诉他需要处理的数据。
    • worker.onmessage:这是一个事件监听器,用于监听工作线程返回的消息。当工作线程完成任务并返回结果时,会触发这个事件,将结果打印到控制台。
    • worker.onerror:同样是一个事件监听器,用于监听工作线程的错误信息。如果工作线程在执行过程中发生错误,会触发这个事件,将错误信息打印到控制台。
  • 工作线程(worker.js)

    • self.onmessage:这是工作线程的事件监听器,用于监听主线程发送的消息。当收到主线程的消息时,会触发这个事件。
    • const number = event.data:从事件对象中获取主线程发送过来的数据。
    • const result = number * number:对获取到的数据进行简单的计算,这里是将数字进行平方运算。
    • self.postMessage(result):将计算结果通过 postMessage 方法返回给主线程。

通过这个示例,我们可以看到 Web Workers 可以很方便地实现主线程和工作线程之间的通信,从而在不阻塞主线程的情况下完成一些复杂的计算任务。

总之,Web Workers 就像是程序员的得力助手,能在复杂的开发场景中帮助我们提高性能、优化用户体验。有了它,我们就可以更加从容地应对各种挑战,开发出更加优秀的网页应用。