收录了这篇文章
JavaScript 在浏览器环境中通常是单线程执行的,这意味着在同一时间只能有一个脚本在运行。这是因为 JavaScript 设计之初是为了操作 DOM 和处理用户交互,如果允许多个脚本同时修改 DOM,那么可能会导致不可预测的行为。
然而,JavaScript 单线程并不意味着它是阻塞的或没有并发能力的。JavaScript 通过其事件循环机制和异步编程模型(如回调函数、Promise、async/await 等),能够实现非阻塞的 I/O 操作和其他异步任务。
但是,在JavaScript中,长时间计算会阻塞UI线程,导致应用无法响应用户操作。为了避免这种情况,可以将长时间计算的代码放在Web Worker中运行。
Web Worker是HTML5引入的一个API,它允许在后台线程中运行脚本,不影响主线程(通常是UI线程)的执行。这样,在Web Worker中进行的计算不会阻塞用户界面。
在现代浏览器中,主要有两种类型的 Worker:
普通工作线程(Workers):
普通工作线程可以在任何标签页中创建,并且它们运行在一个新的线程中。它们可以执行复杂的计算或长时间运行的任务,而不会影响到页面的渲染或者其他交互操作。普通工作线程不能访问 DOM。
共享工作线程(Shared Workers):
共享工作线程允许一个 Worker 被多个标签页或者窗口共享。这对于需要在不同标签页之间共享数据或者资源的应用场景非常有用。与普通工作线程类似,共享工作线程也不能直接访问 DOM。
在 2018 年,JavaScript 引入了 Worker 的一个变种——Web Workers 中的 Service Workers,尽管 Service Worker 也有自己的用途,如缓存资源、处理推送通知等,但它不是直接用于计算任务的。
创建一个普通工作线程的基本语法如下:
// 创建一个新的工作线程实例
const worker = new Worker('worker.js');
// 向工作线程发送消息
worker.postMessage({data: 'Hello Worker'});
// 监听工作线程的消息
worker.onmessage = function(event) {
console.log('Received from worker: ' + event.data);
};
工作线程脚本 worker.js 可以接收消息并进行处理:
self.addEventListener('message', function(event) {
console.log('Received from main thread: ' + event.data);
self.postMessage('Hello Main Thread');
}, false);
注意,不是所有的 JavaScript 函数都可以在工作线程中使用。例如,DOM API 是不可用的。另外,工作线程之间以及工作线程与主线程之间的通信是通过 postMessage 和监听 message 事件来实现的。
如果你想要使用更高级的功能,比如在工作线程中进行异步文件读写,或者使用某些 Web APIs,你需要检查特定浏览器的支持情况。同时,确保你的代码兼容各种浏览器版本。
Node.js 的工作者线程参考 https://nodejs.org/docs/latest/api/worker_threads.html