一、为什么需要多线程?
1.1 JavaScript的单线程困境
javascript
// 主线程中的复杂计算会阻塞UI
function calculatePrimes(max) {
const primes = [];
for (let i = 2; i <= max; i++) {
let isPrime = true;
for (let j = 2; j < i; j++) {
if (i % j === 0) {
isPrime = false;
break;
}
}
if (isPrime) primes.push(i);
}
return primes;
}
// 点击按钮后界面会无法操作一段时间
document.getElementById('calculate').addEventListener('click', () => {
const primes = calculatePrimes(100000); // 阻塞主线程
document.getElementById('result').textContent = `找到 ${primes.length} 个质数`;
});
1.2 Web Workers的核心优势
- 并行执行:在后台线程运行脚本
- 非阻塞UI:保持主线程响应性
- 隔离环境:Worker有自己的全局作用域
- 充分利用多核CPU:现代浏览器支持多Worker并行
二、创建你的第一个Web Worker
2.1 基本结构
html
<!-- index.html -->
<button id="start">开始计算</button>
<div id="result"></div>
<script>
const worker = new Worker('worker.js');
document.getElementById('start').addEventListener('click', () => {
worker.postMessage({ command: 'calculate', max: 100000 });
});
worker.onmessage = (event) => {
document.getElementById('result').textContent =
`找到 ${event.data.count} 个质数`;
};
</script>
javascript
// worker.js
self.onmessage = (event) => {
if (event.data.command === 'calculate') {
const primes = calculatePrimes(event.data.max);
self.postMessage({ count: primes.length });
}
};
function calculatePrimes(max) {
// 同前的质数计算逻辑
}
三、高效数据传递
3.1 结构化克隆算法
javascript
// 主线程
const complexData = {
array: new Float32Array(1000),
date: new Date(),
nested: { value: '可克隆对象' }
};
worker.postMessage(complexData);
// Worker中
self.onmessage = (event) => {
console.log(event.data.date.getFullYear()); // 正确访问
};
3.2 传输大型数据(零拷贝)
javascript
// 传输ArrayBuffer而非复制
const buffer = new ArrayBuffer(1024 * 1024 * 100); // 100MB
// 传统方式(复制数据)
worker.postMessage({ buffer });
// 高效方式(转让所有权)
worker.postMessage({ buffer }, [buffer]);
// 主线程中buffer现在不可用
console.log(buffer.byteLength); // 0
3.3 双向通信模式
javascript
// 主线程
worker.postMessage({ type: 'start', max: 1000000 });
worker.onmessage = (event) => {
if (event.data.type === 'progress') {
console.log(event.data.value);
}
};
// Worker中
self.onmessage = (event) => {
console.log(event.data); // 正确访问
self.postMessage({ type: 'progress', value: 0.1 });
};
总结
如果你喜欢本教程,记得点赞+收藏!关注我获取更多JavaScript开发干货。