Web worker是html5引入的新特性,它允许开发者在浏览器后台运行脚本,从而使得主线程(通常负责UI交互)能够在不被阻塞的情况下运行。
Web Worker环境与主线程有一些不同,因此在Web Worker中使用某些API时会有一些限制。了解这些限制有助于功能的设计和开发。以下是一些常见的API限制及说明:
1、DOM访问限制
不能直接访问DOM
2、Window对象限制
不能访问window对象
3、本地存储限制
不能访问localStorage和sessionStorage
4、可以访问IndexDB
5、XMLHttpRequest(XHR)和Fetch API
6、Canvas 2D和WebGL
7、Web Audio API
可以使用 Web Audio API 进行音频处理
8、WebSocket
支持websocket用于实时通信
9、事件循环
Web Worker有自己的事件循环,用于处理定时任务,网络请求等
10、导入脚本
Web Worker可以使用importScripts方法导入其他的脚本文件
示例:
// mathHelper.js 辅助文件
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
function multiply(a, b) {
return a * b;
}
function divide(a, b) {
if (b !== 0) {
return a / b;
} else {
throw new Error('Division by zero');
}
}
// worker.js webworker脚本文件
importScripts('mathHelper.js');
self.onmessage = function(event) {
const { operation, a, b } = event.data;
try {
let result;
switch (operation) {
case 'add':
result = add(a, b);
break;
case 'subtract':
result = subtract(a, b);
break;
case 'multiply':
result = multiply(a, b);
break;
case 'divide':
result = divide(a, b);
break;
default:
throw new Error('Unknown operation');
}
self.postMessage({ result });
} catch (error) {
self.postMessage({ error: error.message });
}
};
// html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Worker Example</title>
</head>
<body>
<label for="operation">Operation:</label>
<select id="operation">
<option value="add">Add</option>
<option value="subtract">Subtract</option>
<option value="multiply">Multiply</option>
<option value="divide">Divide</option>
</select>
<br>
<label for="a">Number A:</label>
<input type="number" id="a" value="10">
<br>
<label for="b">Number B:</label>
<input type="number" id="b" value="5">
<br>
<button id="calculateButton">Calculate</button>
<pre id="result"></pre>
<script>
// 创建一个新的 Web Worker
const worker = new Worker('worker.js');
// 监听 Web Worker 发送的消息
worker.onmessage = function(event) {
if (event.data.error) {
document.getElementById('result').textContent = `Error: ${event.data.error}`;
} else {
document.getElementById('result').textContent = `Result: ${event.data.result}`;
}
};
// 监听按钮点击事件
document.getElementById('calculateButton').addEventListener('click', function() {
const operation = document.getElementById('operation').value;
const a = parseFloat(document.getElementById('a').value);
const b = parseFloat(document.getElementById('b').value);
worker.postMessage({ operation, a, b });
});
</script>
</body>
</html>
11、self全局对象
self是web worker的全局对象,类似于主线程的window对象。以下是self对象中的一些常用方法和属性:
常用方法
1、消息传递
-
postMessage(data): 向创建该Worker的脚本发送数据
self.postMessage('Hello form Worker') -
onMessage(data): 接收从创建该Worker的脚本发送的消息的事件处理器
self.onMessage = (event)=> { console.log('Receive message', event.data) }
2、定时器
- setTimeout(func, dalay, ...args) 延迟执行一次
- setInterval(func, dalay, ...args) 指定时间间隔重复执行函数
- clearTimeout(timeoutId): 清除setTimeout设置的定时器
- clearInterval(intervalId): 清除setInterval设置的定时器
3、网络请求
fetch(url, option): 发送网络请求
self.fetch('http://api.example.com/data')
.then(response => response.json())
.then(data=> {
self.postMessage(data)
})
.catch(error => {
self.postMessage({'error': error.message })
})
4、导入脚本
importScripts(...urls):导入一个或者多个脚本
self.importScripts('script1', 'script2')
5、终止Worker
close(): 关闭当前Worker
self.close()
常用属性
1、navigator:提供浏览器的信息
console.log(self.navigator.userAgent)
2、location:提供关于Worker脚本URL的信息
console.log(self.location.href)
3、crypto:提供加密相关的功能
self.crypto.getRandomValues(new Uint32Array(1))
4、indexDB: 提供对indexDB数据库的访问
const request = self.indexDB.open('myDatabase', 1);
request.onsuccess = function(event) {
const db = event.target.result;
// 操作数据库
}
示例代码
// worker.js
self.onmessage = function(event) {
if (event.data === 'start') {
start();
}
};
function start() {
// 发送消息
self.postMessage('Hello from worker!');
// 定时器
let count = 0;
let intervalId = self.setInterval(() => {
count++;
self.postMessage(`Count: ${count}`);
}, 1000);
// 网络请求
self.fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => {
self.postMessage(data);
})
.catch(error => {
self.postMessage({ error: error.message });
});
// 导入脚本
self.importScripts('helper.js');
// 终止 Worker
setTimeout(() => {
self.close();
}, 10000);
}
// 主线程代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Worker Example</title>
</head>
<body>
<button id="startButton">Start Worker</button>
<pre id="result"></pre>
<script>
// 创建一个新的 Web Worker
const worker = new Worker('worker.js');
// 监听 Web Worker 发送的消息
worker.onmessage = function(event) {
document.getElementById('result').textContent += event.data + '\n';
};
// 监听按钮点击事件
document.getElementById('startButton').addEventListener('click', function() {
worker.postMessage('start');
});
</script>
</body>
</html>