JS居然也可以多线程!
如果你刚刚开始使用JS,你会怀疑这句话,因为一开始所有人都会告诉你JS是一门单线程语言,多线程是后端独占的,并且告诉你为什么以及event Loop相关知识。并且嘱咐你这就以及足够应对我们的开发场景了。然而实际上,JS可以进行多线程。而且非常简单。
WebWorker:为前端解放多线程
WebWorker是HTML5引入的一项重要特性,它允许我们在浏览器中创建一个独立的后台线程,用于执行一些耗时的任务,而不会阻塞用户界面的渲染和交互。
使用WebWorker,我们可以轻松地将一些计算密集型的任务,比如图像处理、数据计算等,转移到后台线程中执行,释放主线程的压力,提高应用程序的响应速度和用户体验。
一个简单的示例代码,演示了如何使用WebWorker来实现一个计算斐波那契数列的任务:
// 主线程代码
const worker = new Worker('worker.js');
worker.postMessage(10); // 向Worker发送消息
worker.onmessage = function(event) {
console.log(event.data); // 接收Worker返回的结果
};
// Worker线程代码(worker.js)
self.onmessage = function(event) {
const n = event.data;
const result = fibonacci(n); // 计算斐波那契数列
self.postMessage(result); // 将结果发送给主线程
};
function fibonacci(n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
通过上面的代码,我们可以看到,主线程将计算任务交给了WebWorker,并通过postMessage方法发送了一个消息。Worker线程接收到消息后,执行计算任务,并通过postMessage方法将结果发送给主线程。这种分离计算任务和UI渲染的方式,大大提高了应用程序的性能和响应速度。
SharedWorker:让多个页面共享计算资源
SharedWorker允许多个页面共享同一个后台线程,从而实现更高效的资源利用和协同计算。
A页面
const worker = new SharedWorker('Sharedworker.js');
worker.port.onmessage = function(event) {
console.log(event.data); // 接收SharedWorker返回的结果
};
worker.port.postMessage({ type: 'add', operands: [2, 3] });
// 向SharedWorker发送消息
B页面
const worker = new SharedWorker('Sharedworker.js');
worker.port.onmessage = function(event) {
console.log(event.data); // 接收SharedWorker返回的结果
};
worker.port.postMessage({ type: 'multiply', operands: [4, 5] });
// 向SharedWorker发送消息
Sharedworker.js
const ports = [];
self.onconnect = function(event) {
const port = event.ports[0];
ports.push(port);
port.onmessage = function(event) {
const message = event.data;
const result = calculate(message.type, message.operands); // 执行计算任务
ports.forEach(port => port.postMessage(result)); // 将结果发送给所有连接的页面
};
};
function calculate(type, operands) {
if (type === 'add') {
return operands.reduce((a, b) => a + b, 0);
} else if (type === 'multiply') {
return operands.reduce((a, b) => a * b, 1);
}
}
通过上面的代码,我们可以看到,页面A和页面B分别与同一个SharedWorker建立连接,并通过postMessage方法向SharedWorker发送消息。SharedWorker接收到消息后,执行相应的计算任务,并将结果通过postMessage方法发送给所有连接的页面。
这种多页面共享计算资源的方式,不仅减少了重复计算,还实现了页面之间的数据共享和协同计算,提高了系统的整体性能和可扩展性。
使用限制
同源策略:客户端工作线程受到同源策略的限制,即只能与同源的脚本进行通信。这意味着客户端工作线程只能与与其来源相同的脚本进行交互,无法直接与其他域的脚本进行通信。(SharedWorker)
无法访问DOM:客户端工作线程不能直接访问或操作浏览器的DOM(文档对象模型)。这是为了避免多线程操作DOM引发的潜在竞态条件和不确定性。如果需要操作DOM,可以通过与主线程进行通信来委托主线程执行相关操作。
无法访问某些API:客户端工作线程无法直接访问一些浏览器API,如
window
对象、document
对象、alert()
函数等。这些功能只能通过与主线程进行通信来间接访问。不是所有浏览器都支持:尽管现代浏览器普遍支持客户端工作线程,但并不是所有浏览器都支持该功能。一些旧版本的浏览器可能不支持或提供有限支持。
ServiceWorker:细粒度地缓存资源
service worker同样是workers的另一个类型。但是由于目前支持度不是很高,所以还是遇到很大的兼容性的问题,得不到广泛的使用。
同步API(如XHR和localStorage)不能在service worker中使用。
出于安全考量,Service workers只能由·HTTPS承载
具体的内容我会在未来专门书写一个PWA指南来更好的讲解该功能,先鸽了。