Search K
Appearance
Appearance
Worker, postMessage, onmessage, onerror, terminate, importScripts, SharedWorker, ServiceWorker, MessagePort, transferable objects
Web Workers是HTML5提供的一种在后台运行JavaScript的机制,允许创建独立的线程来执行计算密集型任务,而不会阻塞用户界面的响应。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Workers基础</title>
</head>
<body>
<h1>Web Workers基础示例</h1>
<!-- 控制面板 -->
<section class="control-panel">
<h2>控制面板</h2>
<button id="start-worker">启动Worker</button>
<button id="stop-worker">停止Worker</button>
<button id="send-message">发送消息</button>
<input type="text" id="message-input" placeholder="输入要发送的消息">
</section>
<!-- 状态显示 -->
<section class="status-display">
<h2>Worker状态</h2>
<div id="worker-status" role="status" aria-live="polite">
未启动
</div>
</section>
<!-- 消息日志 -->
<section class="message-log">
<h2>消息日志</h2>
<div id="message-log" role="log" aria-live="polite"></div>
</section>
<!-- 性能监控 -->
<section class="performance-monitor">
<h2>性能监控</h2>
<div id="performance-info">
<p>主线程状态: <span id="main-thread-status">空闲</span></p>
<p>Worker线程状态: <span id="worker-thread-status">未启动</span></p>
</div>
</section>
<script>
// Web Workers基础实现
document.addEventListener('DOMContentLoaded', function() {
const startButton = document.getElementById('start-worker');
const stopButton = document.getElementById('stop-worker');
const sendButton = document.getElementById('send-message');
const messageInput = document.getElementById('message-input');
const workerStatus = document.getElementById('worker-status');
const messageLog = document.getElementById('message-log');
const mainThreadStatus = document.getElementById('main-thread-status');
const workerThreadStatus = document.getElementById('worker-thread-status');
let worker = null;
// 启动Worker
startButton.addEventListener('click', function() {
if (!worker) {
// 创建Worker实例
worker = new Worker('worker.js');
// 监听Worker消息
worker.onmessage = function(e) {
handleWorkerMessage(e.data);
};
// 监听Worker错误
worker.onerror = function(e) {
handleWorkerError(e);
};
updateStatus('Worker已启动');
workerThreadStatus.textContent = '运行中';
}
});
// 停止Worker
stopButton.addEventListener('click', function() {
if (worker) {
worker.terminate();
worker = null;
updateStatus('Worker已停止');
workerThreadStatus.textContent = '已停止';
}
});
// 发送消息
sendButton.addEventListener('click', function() {
if (worker && messageInput.value.trim()) {
const message = messageInput.value.trim();
worker.postMessage(message);
logMessage('发送到Worker: ' + message);
messageInput.value = '';
}
});
// 处理Worker消息
function handleWorkerMessage(data) {
logMessage('收到Worker消息: ' + data);
}
// 处理Worker错误
function handleWorkerError(error) {
logMessage('Worker错误: ' + error.message);
}
// 更新状态
function updateStatus(status) {
workerStatus.textContent = status;
}
// 记录消息
function logMessage(message) {
const logEntry = document.createElement('div');
logEntry.textContent = new Date().toLocaleTimeString() + ': ' + message;
messageLog.appendChild(logEntry);
messageLog.scrollTop = messageLog.scrollHeight;
}
});
</script>
</body>
</html><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Workers类型</title>
</head>
<body>
<h1>Web Workers类型示例</h1>
<!-- Dedicated Worker -->
<section class="dedicated-worker">
<h2>Dedicated Worker</h2>
<p>专用Worker,只能被创建它的脚本访问</p>
<button id="create-dedicated">创建Dedicated Worker</button>
<div id="dedicated-result" role="region" aria-live="polite"></div>
</section>
<!-- Shared Worker -->
<section class="shared-worker">
<h2>Shared Worker</h2>
<p>共享Worker,可以被多个脚本访问</p>
<button id="create-shared">创建Shared Worker</button>
<div id="shared-result" role="region" aria-live="polite"></div>
</section>
<!-- Service Worker -->
<section class="service-worker">
<h2>Service Worker</h2>
<p>服务Worker,用于网络代理和缓存</p>
<button id="register-service">注册Service Worker</button>
<div id="service-result" role="region" aria-live="polite"></div>
</section>
<script>
// Web Workers类型实现
document.addEventListener('DOMContentLoaded', function() {
// Dedicated Worker
document.getElementById('create-dedicated').addEventListener('click', function() {
const dedicatedResult = document.getElementById('dedicated-result');
try {
const worker = new Worker('dedicated-worker.js');
worker.postMessage('Hello from main thread');
worker.onmessage = function(e) {
dedicatedResult.innerHTML = `
<h3>Dedicated Worker响应</h3>
<p>消息: ${e.data}</p>
<p>时间: ${new Date().toLocaleString()}</p>
`;
};
worker.onerror = function(e) {
dedicatedResult.innerHTML = `
<h3>错误</h3>
<p>错误信息: ${e.message}</p>
`;
};
} catch (error) {
dedicatedResult.innerHTML = `
<h3>创建失败</h3>
<p>错误: ${error.message}</p>
`;
}
});
// Shared Worker
document.getElementById('create-shared').addEventListener('click', function() {
const sharedResult = document.getElementById('shared-result');
try {
const worker = new SharedWorker('shared-worker.js');
const port = worker.port;
port.start();
port.postMessage('Hello from main thread');
port.onmessage = function(e) {
sharedResult.innerHTML = `
<h3>Shared Worker响应</h3>
<p>消息: ${e.data}</p>
<p>时间: ${new Date().toLocaleString()}</p>
`;
};
port.onerror = function(e) {
sharedResult.innerHTML = `
<h3>错误</h3>
<p>错误信息: ${e.message}</p>
`;
};
} catch (error) {
sharedResult.innerHTML = `
<h3>创建失败</h3>
<p>错误: ${error.message}</p>
`;
}
});
// Service Worker
document.getElementById('register-service').addEventListener('click', function() {
const serviceResult = document.getElementById('service-result');
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js')
.then(function(registration) {
serviceResult.innerHTML = `
<h3>Service Worker注册成功</h3>
<p>作用域: ${registration.scope}</p>
<p>状态: ${registration.active ? '活动' : '未活动'}</p>
`;
})
.catch(function(error) {
serviceResult.innerHTML = `
<h3>注册失败</h3>
<p>错误: ${error.message}</p>
`;
});
} else {
serviceResult.innerHTML = `
<h3>不支持</h3>
<p>浏览器不支持Service Worker</p>
`;
}
});
});
</script>
</body>
</html>Web Workers通过消息传递机制与主线程通信,使用postMessage发送消息,onmessage接收消息。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Worker通信机制</title>
</head>
<body>
<h1>Worker通信机制示例</h1>
<!-- 数据输入区 -->
<section class="data-input">
<h2>数据输入</h2>
<div class="input-group">
<label for="number-input">数字 (用于计算):</label>
<input type="number" id="number-input" value="1000000" min="1">
</div>
<div class="input-group">
<label for="text-input">文本 (用于处理):</label>
<textarea id="text-input" placeholder="输入要处理的文本"></textarea>
</div>
<div class="input-group">
<label for="json-input">JSON数据:</label>
<textarea id="json-input" placeholder='{"key": "value"}'></textarea>
</div>
</section>
<!-- 操作按钮 -->
<section class="operations">
<h2>操作</h2>
<button id="calculate-fibonacci">计算斐波那契数列</button>
<button id="process-text">处理文本</button>
<button id="process-json">处理JSON</button>
<button id="send-array">发送数组</button>
<button id="transfer-buffer">传输ArrayBuffer</button>
</section>
<!-- 结果显示 -->
<section class="results">
<h2>处理结果</h2>
<div id="result-display" role="region" aria-live="polite"></div>
</section>
<!-- 性能监控 -->
<section class="performance">
<h2>性能监控</h2>
<div id="performance-display">
<p>处理时间: <span id="processing-time">-</span></p>
<p>数据大小: <span id="data-size">-</span></p>
<p>传输方式: <span id="transfer-method">-</span></p>
</div>
</section>
<script>
// Worker通信机制实现
document.addEventListener('DOMContentLoaded', function() {
const numberInput = document.getElementById('number-input');
const textInput = document.getElementById('text-input');
const jsonInput = document.getElementById('json-input');
const resultDisplay = document.getElementById('result-display');
const processingTime = document.getElementById('processing-time');
const dataSize = document.getElementById('data-size');
const transferMethod = document.getElementById('transfer-method');
let worker = null;
let startTime = 0;
// 创建Worker
function createWorker() {
if (!worker) {
worker = new Worker('communication-worker.js');
worker.onmessage = function(e) {
const endTime = performance.now();
const duration = endTime - startTime;
handleWorkerResponse(e.data, duration);
};
worker.onerror = function(e) {
displayError('Worker错误: ' + e.message);
};
}
return worker;
}
// 计算斐波那契数列
document.getElementById('calculate-fibonacci').addEventListener('click', function() {
const n = parseInt(numberInput.value);
if (isNaN(n) || n <= 0) {
displayError('请输入有效的正整数');
return;
}
const currentWorker = createWorker();
startTime = performance.now();
currentWorker.postMessage({
type: 'fibonacci',
data: n
});
updatePerformanceInfo(JSON.stringify({type: 'fibonacci', data: n}), 'postMessage');
displayMessage('正在计算斐波那契数列...');
});
// 处理文本
document.getElementById('process-text').addEventListener('click', function() {
const text = textInput.value.trim();
if (!text) {
displayError('请输入要处理的文本');
return;
}
const currentWorker = createWorker();
startTime = performance.now();
currentWorker.postMessage({
type: 'processText',
data: text
});
updatePerformanceInfo(text, 'postMessage');
displayMessage('正在处理文本...');
});
// 处理JSON
document.getElementById('process-json').addEventListener('click', function() {
const jsonText = jsonInput.value.trim();
if (!jsonText) {
displayError('请输入JSON数据');
return;
}
try {
const jsonData = JSON.parse(jsonText);
const currentWorker = createWorker();
startTime = performance.now();
currentWorker.postMessage({
type: 'processJson',
data: jsonData
});
updatePerformanceInfo(jsonText, 'postMessage');
displayMessage('正在处理JSON数据...');
} catch (error) {
displayError('JSON格式错误: ' + error.message);
}
});
// 发送数组
document.getElementById('send-array').addEventListener('click', function() {
const arraySize = parseInt(numberInput.value);
const largeArray = new Array(arraySize).fill(0).map((_, i) => i);
const currentWorker = createWorker();
startTime = performance.now();
currentWorker.postMessage({
type: 'processArray',
data: largeArray
});
updatePerformanceInfo(`数组(${arraySize}个元素)`, 'postMessage (复制)');
displayMessage('正在处理数组...');
});
// 传输ArrayBuffer
document.getElementById('transfer-buffer').addEventListener('click', function() {
const bufferSize = parseInt(numberInput.value);
const buffer = new ArrayBuffer(bufferSize * 4);
const view = new Int32Array(buffer);
// 填充数据
for (let i = 0; i < bufferSize; i++) {
view[i] = i;
}
const currentWorker = createWorker();
startTime = performance.now();
// 使用Transferable Objects传输
currentWorker.postMessage({
type: 'processBuffer',
data: buffer
}, [buffer]);
updatePerformanceInfo(`ArrayBuffer(${bufferSize * 4}字节)`, 'postMessage (传输)');
displayMessage('正在传输ArrayBuffer...');
});
// 处理Worker响应
function handleWorkerResponse(data, duration) {
processingTime.textContent = duration.toFixed(2) + 'ms';
if (data.error) {
displayError(data.error);
} else {
displayResult(data);
}
}
// 显示结果
function displayResult(data) {
let resultHtml = '<h3>处理结果</h3>';
switch (data.type) {
case 'fibonacci':
resultHtml += `
<p>斐波那契数列第${data.input}项: ${data.result}</p>
<p>计算步骤: ${data.steps || '未知'}</p>
`;
break;
case 'processText':
resultHtml += `
<p>原文本长度: ${data.originalLength}</p>
<p>处理后长度: ${data.processedLength}</p>
<p>单词数: ${data.wordCount}</p>
<p>字符统计: ${JSON.stringify(data.charCount)}</p>
`;
break;
case 'processJson':
resultHtml += `
<p>JSON对象属性数: ${data.propertyCount}</p>
<p>处理后的数据: ${JSON.stringify(data.result)}</p>
`;
break;
case 'processArray':
resultHtml += `
<p>数组长度: ${data.length}</p>
<p>总和: ${data.sum}</p>
<p>平均值: ${data.average}</p>
<p>最大值: ${data.max}</p>
<p>最小值: ${data.min}</p>
`;
break;
case 'processBuffer':
resultHtml += `
<p>缓冲区大小: ${data.bufferSize}字节</p>
<p>元素数量: ${data.elementCount}</p>
<p>处理结果: ${data.result}</p>
`;
break;
}
resultDisplay.innerHTML = resultHtml;
}
// 显示消息
function displayMessage(message) {
resultDisplay.innerHTML = `<p>${message}</p>`;
}
// 显示错误
function displayError(error) {
resultDisplay.innerHTML = `<p style="color: red;">错误: ${error}</p>`;
}
// 更新性能信息
function updatePerformanceInfo(data, method) {
const size = new Blob([JSON.stringify(data)]).size;
dataSize.textContent = size + ' bytes';
transferMethod.textContent = method;
}
});
</script>
</body>
</html><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>复杂数据传输</title>
</head>
<body>
<h1>复杂数据传输示例</h1>
<!-- 数据类型选择 -->
<section class="data-types">
<h2>数据类型</h2>
<div class="type-selector">
<button id="send-object">发送对象</button>
<button id="send-function">发送函数字符串</button>
<button id="send-date">发送日期</button>
<button id="send-regexp">发送正则表达式</button>
<button id="send-file">发送文件数据</button>
</div>
</section>
<!-- 文件输入 -->
<section class="file-input">
<h2>文件输入</h2>
<input type="file" id="file-input" accept="*/*">
</section>
<!-- 传输选项 -->
<section class="transfer-options">
<h2>传输选项</h2>
<div class="options">
<label>
<input type="radio" name="transfer-type" value="copy" checked>
复制传输(默认)
</label>
<label>
<input type="radio" name="transfer-type" value="transfer">
转移传输(Transferable Objects)
</label>
</div>
</section>
<!-- 结果显示 -->
<section class="results">
<h2>传输结果</h2>
<div id="transfer-results" role="region" aria-live="polite"></div>
</section>
<script>
// 复杂数据传输实现
document.addEventListener('DOMContentLoaded', function() {
const fileInput = document.getElementById('file-input');
const transferResults = document.getElementById('transfer-results');
let worker = null;
// 创建Worker
function createWorker() {
if (!worker) {
worker = new Worker('data-transfer-worker.js');
worker.onmessage = function(e) {
handleWorkerMessage(e.data);
};
worker.onerror = function(e) {
displayError('Worker错误: ' + e.message);
};
}
return worker;
}
// 发送对象
document.getElementById('send-object').addEventListener('click', function() {
const complexObject = {
id: Date.now(),
name: '复杂对象',
data: {
numbers: [1, 2, 3, 4, 5],
nested: {
deep: {
value: 'nested value'
}
}
},
metadata: {
created: new Date().toISOString(),
version: '1.0.0'
}
};
sendToWorker('object', complexObject);
});
// 发送函数字符串
document.getElementById('send-function').addEventListener('click', function() {
const functionString = `
function calculateSum(arr) {
return arr.reduce((sum, num) => sum + num, 0);
}
`;
sendToWorker('function', {
code: functionString,
args: [1, 2, 3, 4, 5]
});
});
// 发送日期
document.getElementById('send-date').addEventListener('click', function() {
const dateData = {
current: new Date(),
formatted: new Date().toISOString(),
timestamp: Date.now()
};
sendToWorker('date', dateData);
});
// 发送正则表达式
document.getElementById('send-regexp').addEventListener('click', function() {
const regexData = {
pattern: /\b\w+\b/g,
patternString: '\\b\\w+\\b',
flags: 'g',
testString: 'Hello World! This is a test.'
};
sendToWorker('regexp', regexData);
});
// 发送文件数据
document.getElementById('send-file').addEventListener('click', function() {
const file = fileInput.files[0];
if (!file) {
displayError('请选择一个文件');
return;
}
const reader = new FileReader();
reader.onload = function(e) {
const fileData = {
name: file.name,
size: file.size,
type: file.type,
lastModified: file.lastModified,
content: e.target.result
};
sendToWorker('file', fileData);
};
reader.readAsDataURL(file);
});
// 发送数据到Worker
function sendToWorker(type, data) {
const currentWorker = createWorker();
const transferType = document.querySelector('input[name="transfer-type"]:checked').value;
const message = {
type: type,
data: data,
transferType: transferType,
timestamp: Date.now()
};
displayMessage('正在发送数据...');
if (transferType === 'transfer' && type === 'file' && data.content.startsWith('data:')) {
// 对于某些数据类型,尝试使用Transferable Objects
try {
const buffer = new ArrayBuffer(data.size);
currentWorker.postMessage(message, [buffer]);
} catch (error) {
// 回退到复制传输
currentWorker.postMessage(message);
}
} else {
currentWorker.postMessage(message);
}
}
// 处理Worker消息
function handleWorkerMessage(data) {
if (data.error) {
displayError(data.error);
} else {
displayResult(data);
}
}
// 显示结果
function displayResult(data) {
let resultHtml = `
<h3>传输成功</h3>
<p>数据类型: ${data.type}</p>
<p>处理时间: ${data.processingTime}ms</p>
<p>数据大小: ${data.dataSize} bytes</p>
`;
switch (data.type) {
case 'object':
resultHtml += `
<h4>对象处理结果</h4>
<p>属性数量: ${data.result.propertyCount}</p>
<p>嵌套深度: ${data.result.nestingDepth}</p>
<p>数组元素: ${data.result.arrayElements}</p>
`;
break;
case 'function':
resultHtml += `
<h4>函数执行结果</h4>
<p>执行结果: ${data.result.executionResult}</p>
<p>函数名: ${data.result.functionName}</p>
`;
break;
case 'date':
resultHtml += `
<h4>日期处理结果</h4>
<p>格式化日期: ${data.result.formatted}</p>
<p>时间戳: ${data.result.timestamp}</p>
<p>时区: ${data.result.timezone}</p>
`;
break;
case 'regexp':
resultHtml += `
<h4>正则表达式处理结果</h4>
<p>匹配结果: ${JSON.stringify(data.result.matches)}</p>
<p>匹配数量: ${data.result.matchCount}</p>
`;
break;
case 'file':
resultHtml += `
<h4>文件处理结果</h4>
<p>文件名: ${data.result.fileName}</p>
<p>文件大小: ${data.result.fileSize} bytes</p>
<p>文件类型: ${data.result.fileType}</p>
<p>内容预览: ${data.result.contentPreview}</p>
`;
break;
}
transferResults.innerHTML = resultHtml;
}
// 显示消息
function displayMessage(message) {
transferResults.innerHTML = `<p>${message}</p>`;
}
// 显示错误
function displayError(error) {
transferResults.innerHTML = `<p style="color: red;">错误: ${error}</p>`;
}
});
</script>
</body>
</html><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Worker文件管理</title>
</head>
<body>
<h1>Worker文件管理示例</h1>
<!-- 文件结构说明 -->
<section class="file-structure">
<h2>推荐的文件结构</h2>
<pre>
project/
├── index.html
├── js/
│ ├── main.js
│ └── workers/
│ ├── calculation-worker.js
│ ├── data-processing-worker.js
│ └── shared/
│ ├── utils.js
│ └── constants.js
└── data/
└── sample-data.json
</pre>
</section>
<!-- Worker管理界面 -->
<section class="worker-management">
<h2>Worker管理</h2>
<div class="worker-controls">
<button id="create-calculation-worker">创建计算Worker</button>
<button id="create-data-worker">创建数据处理Worker</button>
<button id="import-scripts">导入脚本</button>
<button id="cleanup-workers">清理Workers</button>
</div>
<div class="worker-status">
<h3>Worker状态</h3>
<div id="worker-status-list" role="list"></div>
</div>
</section>
<!-- 脚本导入测试 -->
<section class="script-import">
<h2>脚本导入测试</h2>
<div class="import-controls">
<input type="url" id="script-url" placeholder="输入脚本URL">
<button id="import-external">导入外部脚本</button>
</div>
<div id="import-results" role="region" aria-live="polite"></div>
</section>
<!-- 错误处理 -->
<section class="error-handling">
<h2>错误处理</h2>
<div class="error-controls">
<button id="trigger-error">触发错误</button>
<button id="test-invalid-worker">测试无效Worker</button>
<button id="test-network-error">测试网络错误</button>
</div>
<div id="error-log" role="log" aria-live="polite"></div>
</section>
<script>
// Worker文件管理实现
document.addEventListener('DOMContentLoaded', function() {
const workerStatusList = document.getElementById('worker-status-list');
const importResults = document.getElementById('import-results');
const errorLog = document.getElementById('error-log');
const scriptUrl = document.getElementById('script-url');
let workers = new Map();
let workerIdCounter = 0;
// 创建计算Worker
document.getElementById('create-calculation-worker').addEventListener('click', function() {
createWorker('calculation-worker.js', 'calculation');
});
// 创建数据处理Worker
document.getElementById('create-data-worker').addEventListener('click', function() {
createWorker('data-processing-worker.js', 'data-processing');
});
// 导入脚本
document.getElementById('import-scripts').addEventListener('click', function() {
testImportScripts();
});
// 清理Workers
document.getElementById('cleanup-workers').addEventListener('click', function() {
cleanupWorkers();
});
// 导入外部脚本
document.getElementById('import-external').addEventListener('click', function() {
const url = scriptUrl.value.trim();
if (url) {
importExternalScript(url);
} else {
displayError('请输入有效的脚本URL');
}
});
// 触发错误
document.getElementById('trigger-error').addEventListener('click', function() {
triggerWorkerError();
});
// 测试无效Worker
document.getElementById('test-invalid-worker').addEventListener('click', function() {
testInvalidWorker();
});
// 测试网络错误
document.getElementById('test-network-error').addEventListener('click', function() {
testNetworkError();
});
// 创建Worker
function createWorker(scriptPath, type) {
const workerId = ++workerIdCounter;
const workerName = `${type}-${workerId}`;
try {
const worker = new Worker(scriptPath);
worker.onmessage = function(e) {
handleWorkerMessage(workerName, e.data);
};
worker.onerror = function(e) {
handleWorkerError(workerName, e);
};
workers.set(workerName, {
worker: worker,
type: type,
created: new Date(),
status: 'active'
});
updateWorkerStatus();
// 发送初始化消息
worker.postMessage({
type: 'init',
workerId: workerId,
workerName: workerName
});
} catch (error) {
displayError(`创建Worker失败: ${error.message}`);
}
}
// 测试脚本导入
function testImportScripts() {
const worker = new Worker('import-scripts-worker.js');
worker.onmessage = function(e) {
importResults.innerHTML = `
<h3>脚本导入结果</h3>
<p>状态: ${e.data.status}</p>
<p>导入的脚本: ${e.data.scripts.join(', ')}</p>
<p>可用函数: ${e.data.availableFunctions.join(', ')}</p>
`;
};
worker.onerror = function(e) {
importResults.innerHTML = `
<h3>脚本导入失败</h3>
<p>错误: ${e.message}</p>
`;
};
worker.postMessage({type: 'importScripts'});
}
// 导入外部脚本
function importExternalScript(url) {
const worker = new Worker('external-import-worker.js');
worker.onmessage = function(e) {
if (e.data.success) {
importResults.innerHTML = `
<h3>外部脚本导入成功</h3>
<p>URL: ${url}</p>
<p>响应: ${JSON.stringify(e.data.result)}</p>
`;
} else {
importResults.innerHTML = `
<h3>外部脚本导入失败</h3>
<p>错误: ${e.data.error}</p>
`;
}
};
worker.onerror = function(e) {
importResults.innerHTML = `
<h3>Worker错误</h3>
<p>错误: ${e.message}</p>
`;
};
worker.postMessage({
type: 'importExternal',
url: url
});
}
// 清理Workers
function cleanupWorkers() {
let terminatedCount = 0;
workers.forEach((workerInfo, name) => {
if (workerInfo.status === 'active') {
workerInfo.worker.terminate();
workerInfo.status = 'terminated';
terminatedCount++;
}
});
workers.clear();
updateWorkerStatus();
displayMessage(`已清理${terminatedCount}个Worker`);
}
// 触发Worker错误
function triggerWorkerError() {
const worker = new Worker('error-worker.js');
worker.onmessage = function(e) {
displayMessage('Worker正常响应: ' + e.data);
};
worker.onerror = function(e) {
displayError(`Worker错误: ${e.message} (${e.filename}:${e.lineno})`);
};
worker.postMessage({type: 'triggerError'});
}
// 测试无效Worker
function testInvalidWorker() {
try {
const worker = new Worker('non-existent-worker.js');
worker.onerror = function(e) {
displayError(`无效Worker错误: ${e.message}`);
};
worker.postMessage({type: 'test'});
} catch (error) {
displayError(`创建无效Worker失败: ${error.message}`);
}
}
// 测试网络错误
function testNetworkError() {
try {
const worker = new Worker('https://invalid-domain-for-testing.com/worker.js');
worker.onerror = function(e) {
displayError(`网络错误: ${e.message}`);
};
worker.postMessage({type: 'test'});
} catch (error) {
displayError(`网络Worker创建失败: ${error.message}`);
}
}
// 处理Worker消息
function handleWorkerMessage(workerName, data) {
displayMessage(`Worker ${workerName}: ${JSON.stringify(data)}`);
}
// 处理Worker错误
function handleWorkerError(workerName, error) {
displayError(`Worker ${workerName} 错误: ${error.message}`);
// 更新Worker状态
if (workers.has(workerName)) {
workers.get(workerName).status = 'error';
updateWorkerStatus();
}
}
// 更新Worker状态
function updateWorkerStatus() {
let statusHtml = '';
if (workers.size === 0) {
statusHtml = '<p>没有活动的Worker</p>';
} else {
workers.forEach((workerInfo, name) => {
statusHtml += `
<div class="worker-item" role="listitem">
<h4>${name}</h4>
<p>类型: ${workerInfo.type}</p>
<p>状态: ${workerInfo.status}</p>
<p>创建时间: ${workerInfo.created.toLocaleString()}</p>
<button onclick="terminateWorker('${name}')">终止</button>
</div>
`;
});
}
workerStatusList.innerHTML = statusHtml;
}
// 终止Worker
window.terminateWorker = function(workerName) {
if (workers.has(workerName)) {
const workerInfo = workers.get(workerName);
workerInfo.worker.terminate();
workerInfo.status = 'terminated';
updateWorkerStatus();
displayMessage(`Worker ${workerName} 已终止`);
}
};
// 显示消息
function displayMessage(message) {
const logEntry = document.createElement('div');
logEntry.textContent = `${new Date().toLocaleTimeString()}: ${message}`;
errorLog.appendChild(logEntry);
errorLog.scrollTop = errorLog.scrollHeight;
}
// 显示错误
function displayError(error) {
const logEntry = document.createElement('div');
logEntry.style.color = 'red';
logEntry.textContent = `${new Date().toLocaleTimeString()}: ${error}`;
errorLog.appendChild(logEntry);
errorLog.scrollTop = errorLog.scrollHeight;
}
});
</script>
</body>
</html><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Workers性能优化</title>
</head>
<body>
<h1>Web Workers性能优化应用</h1>
<!-- 性能测试控制 -->
<section class="performance-controls">
<h2>性能测试</h2>
<div class="test-controls">
<button id="test-main-thread">主线程处理</button>
<button id="test-worker-thread">Worker线程处理</button>
<button id="test-parallel">并行处理</button>
<button id="test-batch">批处理</button>
</div>
<div class="test-settings">
<label>
数据量:
<select id="data-size">
<option value="1000">1,000</option>
<option value="10000">10,000</option>
<option value="100000" selected>100,000</option>
<option value="1000000">1,000,000</option>
</select>
</label>
<label>
Worker数量:
<select id="worker-count">
<option value="1">1</option>
<option value="2">2</option>
<option value="4" selected>4</option>
<option value="8">8</option>
</select>
</label>
</div>
</section>
<!-- 性能监控 -->
<section class="performance-monitor">
<h2>性能监控</h2>
<div class="monitor-display">
<div class="metric">
<h3>主线程</h3>
<p>处理时间: <span id="main-time">-</span></p>
<p>CPU使用率: <span id="main-cpu">-</span></p>
<p>内存使用: <span id="main-memory">-</span></p>
</div>
<div class="metric">
<h3>Worker线程</h3>
<p>处理时间: <span id="worker-time">-</span></p>
<p>并行度: <span id="parallelism">-</span></p>
<p>效率提升: <span id="efficiency">-</span></p>
</div>
</div>
<div class="progress-bars">
<div class="progress-item">
<label>主线程进度:</label>
<progress id="main-progress" max="100" value="0"></progress>
<span id="main-progress-text">0%</span>
</div>
<div class="progress-item">
<label>Worker进度:</label>
<progress id="worker-progress" max="100" value="0"></progress>
<span id="worker-progress-text">0%</span>
</div>
</div>
</section>
<!-- 结果对比 -->
<section class="results-comparison">
<h2>结果对比</h2>
<div id="comparison-chart" role="img" aria-label="性能对比图表"></div>
<div id="results-summary" role="region" aria-live="polite"></div>
</section>
<!-- 实时界面响应测试 -->
<section class="responsiveness-test">
<h2>界面响应性测试</h2>
<div class="interactive-elements">
<button id="ui-test-button">点击测试响应性</button>
<input type="range" id="ui-test-slider" min="0" max="100" value="50">
<span id="slider-value">50</span>
</div>
<div id="responsiveness-log" role="log" aria-live="polite"></div>
</section>
<script>
// Web Workers性能优化实现
document.addEventListener('DOMContentLoaded', function() {
const dataSizeSelect = document.getElementById('data-size');
const workerCountSelect = document.getElementById('worker-count');
const mainTime = document.getElementById('main-time');
const workerTime = document.getElementById('worker-time');
const mainCpu = document.getElementById('main-cpu');
const mainMemory = document.getElementById('main-memory');
const parallelism = document.getElementById('parallelism');
const efficiency = document.getElementById('efficiency');
const mainProgress = document.getElementById('main-progress');
const workerProgress = document.getElementById('worker-progress');
const mainProgressText = document.getElementById('main-progress-text');
const workerProgressText = document.getElementById('worker-progress-text');
const resultsSummary = document.getElementById('results-summary');
const responsivenessLog = document.getElementById('responsiveness-log');
const uiTestButton = document.getElementById('ui-test-button');
const uiTestSlider = document.getElementById('ui-test-slider');
const sliderValue = document.getElementById('slider-value');
let workers = [];
let performanceData = [];
// 界面响应性测试
uiTestButton.addEventListener('click', function() {
const timestamp = performance.now();
logResponsiveness(`按钮点击响应时间: ${timestamp.toFixed(2)}ms`);
});
uiTestSlider.addEventListener('input', function() {
sliderValue.textContent = this.value;
logResponsiveness(`滑块值更新: ${this.value}`);
});
// 主线程处理测试
document.getElementById('test-main-thread').addEventListener('click', function() {
const dataSize = parseInt(dataSizeSelect.value);
testMainThreadProcessing(dataSize);
});
// Worker线程处理测试
document.getElementById('test-worker-thread').addEventListener('click', function() {
const dataSize = parseInt(dataSizeSelect.value);
testWorkerThreadProcessing(dataSize);
});
// 并行处理测试
document.getElementById('test-parallel').addEventListener('click', function() {
const dataSize = parseInt(dataSizeSelect.value);
const workerCount = parseInt(workerCountSelect.value);
testParallelProcessing(dataSize, workerCount);
});
// 批处理测试
document.getElementById('test-batch').addEventListener('click', function() {
const dataSize = parseInt(dataSizeSelect.value);
const workerCount = parseInt(workerCountSelect.value);
testBatchProcessing(dataSize, workerCount);
});
// 主线程处理
function testMainThreadProcessing(dataSize) {
const startTime = performance.now();
const startMemory = performance.memory ? performance.memory.usedJSHeapSize : 0;
// 生成测试数据
const data = generateTestData(dataSize);
// 模拟CPU密集型任务
let progress = 0;
const batchSize = Math.ceil(dataSize / 100);
function processBatch(index) {
const endIndex = Math.min(index + batchSize, dataSize);
// 处理数据批次
for (let i = index; i < endIndex; i++) {
data[i] = Math.sqrt(data[i]) * Math.sin(data[i]);
}
progress = Math.round((endIndex / dataSize) * 100);
updateProgress(mainProgress, mainProgressText, progress);
if (endIndex < dataSize) {
// 使用setTimeout避免完全阻塞UI
setTimeout(() => processBatch(endIndex), 0);
} else {
// 处理完成
const endTime = performance.now();
const endMemory = performance.memory ? performance.memory.usedJSHeapSize : 0;
const processingTime = endTime - startTime;
const memoryUsed = endMemory - startMemory;
mainTime.textContent = processingTime.toFixed(2) + 'ms';
mainMemory.textContent = formatBytes(memoryUsed);
recordPerformanceData('主线程', processingTime, 1, dataSize);
updateResultsSummary();
}
}
processBatch(0);
}
// Worker线程处理
function testWorkerThreadProcessing(dataSize) {
const startTime = performance.now();
const worker = new Worker('performance-worker.js');
worker.onmessage = function(e) {
if (e.data.type === 'progress') {
updateProgress(workerProgress, workerProgressText, e.data.progress);
} else if (e.data.type === 'complete') {
const endTime = performance.now();
const processingTime = endTime - startTime;
workerTime.textContent = processingTime.toFixed(2) + 'ms';
parallelism.textContent = '1';
recordPerformanceData('Worker线程', processingTime, 1, dataSize);
updateResultsSummary();
worker.terminate();
}
};
worker.onerror = function(e) {
logResponsiveness('Worker错误: ' + e.message);
};
worker.postMessage({
type: 'process',
dataSize: dataSize
});
}
// 并行处理
function testParallelProcessing(dataSize, workerCount) {
const startTime = performance.now();
const chunkSize = Math.ceil(dataSize / workerCount);
let completedWorkers = 0;
let totalProgress = 0;
workers = [];
for (let i = 0; i < workerCount; i++) {
const worker = new Worker('performance-worker.js');
const startIndex = i * chunkSize;
const endIndex = Math.min(startIndex + chunkSize, dataSize);
worker.onmessage = function(e) {
if (e.data.type === 'progress') {
totalProgress += e.data.progress / workerCount;
updateProgress(workerProgress, workerProgressText, Math.round(totalProgress));
} else if (e.data.type === 'complete') {
completedWorkers++;
if (completedWorkers === workerCount) {
const endTime = performance.now();
const processingTime = endTime - startTime;
workerTime.textContent = processingTime.toFixed(2) + 'ms';
parallelism.textContent = workerCount;
recordPerformanceData('并行处理', processingTime, workerCount, dataSize);
updateResultsSummary();
// 清理Workers
workers.forEach(w => w.terminate());
workers = [];
}
}
};
worker.postMessage({
type: 'processChunk',
startIndex: startIndex,
endIndex: endIndex,
workerId: i
});
workers.push(worker);
}
}
// 批处理
function testBatchProcessing(dataSize, workerCount) {
const startTime = performance.now();
const batchSize = Math.ceil(dataSize / (workerCount * 10)); // 更小的批次
let processedBatches = 0;
let totalBatches = Math.ceil(dataSize / batchSize);
let currentBatch = 0;
workers = [];
function createWorker() {
const worker = new Worker('performance-worker.js');
worker.onmessage = function(e) {
if (e.data.type === 'complete') {
processedBatches++;
const progress = Math.round((processedBatches / totalBatches) * 100);
updateProgress(workerProgress, workerProgressText, progress);
if (currentBatch < totalBatches) {
// 处理下一批
const startIndex = currentBatch * batchSize;
const endIndex = Math.min(startIndex + batchSize, dataSize);
worker.postMessage({
type: 'processChunk',
startIndex: startIndex,
endIndex: endIndex,
workerId: currentBatch
});
currentBatch++;
} else {
// 所有批次完成
worker.terminate();
if (processedBatches >= totalBatches) {
const endTime = performance.now();
const processingTime = endTime - startTime;
workerTime.textContent = processingTime.toFixed(2) + 'ms';
parallelism.textContent = workerCount + ' (批处理)';
recordPerformanceData('批处理', processingTime, workerCount, dataSize);
updateResultsSummary();
}
}
}
};
return worker;
}
// 创建初始Workers
for (let i = 0; i < workerCount && i < totalBatches; i++) {
const worker = createWorker();
const startIndex = currentBatch * batchSize;
const endIndex = Math.min(startIndex + batchSize, dataSize);
worker.postMessage({
type: 'processChunk',
startIndex: startIndex,
endIndex: endIndex,
workerId: currentBatch
});
currentBatch++;
workers.push(worker);
}
}
// 生成测试数据
function generateTestData(size) {
const data = new Array(size);
for (let i = 0; i < size; i++) {
data[i] = Math.random() * 1000;
}
return data;
}
// 更新进度
function updateProgress(progressElement, textElement, progress) {
progressElement.value = progress;
textElement.textContent = progress + '%';
}
// 记录性能数据
function recordPerformanceData(method, time, workers, dataSize) {
performanceData.push({
method: method,
time: time,
workers: workers,
dataSize: dataSize,
timestamp: new Date()
});
}
// 更新结果摘要
function updateResultsSummary() {
if (performanceData.length < 2) return;
const latest = performanceData[performanceData.length - 1];
const baseline = performanceData.find(d => d.method === '主线程');
if (baseline && latest.method !== '主线程') {
const speedup = baseline.time / latest.time;
efficiency.textContent = speedup.toFixed(2) + 'x';
}
let summaryHtml = '<h3>性能测试结果</h3>';
performanceData.forEach(data => {
summaryHtml += `
<div class="result-item">
<h4>${data.method}</h4>
<p>处理时间: ${data.time.toFixed(2)}ms</p>
<p>Worker数: ${data.workers}</p>
<p>数据量: ${data.dataSize.toLocaleString()}</p>
</div>
`;
});
resultsSummary.innerHTML = summaryHtml;
}
// 记录响应性
function logResponsiveness(message) {
const logEntry = document.createElement('div');
logEntry.textContent = `${new Date().toLocaleTimeString()}: ${message}`;
responsivenessLog.appendChild(logEntry);
// 限制日志数量
if (responsivenessLog.children.length > 10) {
responsivenessLog.removeChild(responsivenessLog.firstChild);
}
}
// 格式化字节
function formatBytes(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
});
</script>
</body>
</html><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据处理Worker应用</title>
</head>
<body>
<h1>数据处理Worker应用</h1>
<!-- 数据生成控制 -->
<section class="data-control">
<h2>数据生成</h2>
<div class="control-group">
<label>数据量: <input type="number" id="data-size" value="100000" min="1000" max="10000000"></label>
<button id="generate-data">生成数据</button>
<button id="clear-data">清除数据</button>
</div>
<div class="data-info">
<p>当前数据量: <span id="current-data-size">0</span></p>
<p>数据大小: <span id="data-memory">0 KB</span></p>
</div>
</section>
<!-- 处理任务 -->
<section class="processing-tasks">
<h2>处理任务</h2>
<div class="task-buttons">
<button id="sort-data">排序数据</button>
<button id="filter-data">过滤数据</button>
<button id="aggregate-data">聚合统计</button>
<button id="transform-data">数据转换</button>
</div>
<div class="task-progress">
<progress id="task-progress" max="100" value="0"></progress>
<span id="progress-text">0%</span>
</div>
</section>
<!-- 结果展示 -->
<section class="results">
<h2>处理结果</h2>
<div id="results-display" role="region" aria-live="polite"></div>
</section>
<script>
// 数据处理Worker应用实现
document.addEventListener('DOMContentLoaded', function() {
const dataSizeInput = document.getElementById('data-size');
const currentDataSize = document.getElementById('current-data-size');
const dataMemory = document.getElementById('data-memory');
const taskProgress = document.getElementById('task-progress');
const progressText = document.getElementById('progress-text');
const resultsDisplay = document.getElementById('results-display');
let currentData = null;
let processingWorker = null;
// 生成数据
document.getElementById('generate-data').addEventListener('click', function() {
const size = parseInt(dataSizeInput.value);
generateData(size);
});
// 清除数据
document.getElementById('clear-data').addEventListener('click', function() {
currentData = null;
currentDataSize.textContent = '0';
dataMemory.textContent = '0 KB';
resultsDisplay.innerHTML = '';
});
// 处理任务
document.getElementById('sort-data').addEventListener('click', () => {
processData('sort');
});
document.getElementById('filter-data').addEventListener('click', () => {
processData('filter');
});
document.getElementById('aggregate-data').addEventListener('click', () => {
processData('aggregate');
});
document.getElementById('transform-data').addEventListener('click', () => {
processData('transform');
});
// 生成数据
function generateData(size) {
if (processingWorker) {
processingWorker.terminate();
}
processingWorker = new Worker('data-processing-worker.js');
processingWorker.onmessage = function(e) {
if (e.data.type === 'dataGenerated') {
currentData = e.data.data;
currentDataSize.textContent = currentData.length.toLocaleString();
// 计算内存使用
const memorySize = JSON.stringify(currentData).length;
dataMemory.textContent = (memorySize / 1024).toFixed(2) + ' KB';
resultsDisplay.innerHTML = '<p>数据生成完成</p>';
}
};
processingWorker.postMessage({
type: 'generateData',
size: size
});
}
// 处理数据
function processData(operation) {
if (!currentData) {
alert('请先生成数据');
return;
}
if (processingWorker) {
processingWorker.terminate();
}
processingWorker = new Worker('data-processing-worker.js');
processingWorker.onmessage = function(e) {
if (e.data.type === 'progress') {
updateProgress(e.data.progress);
} else if (e.data.type === 'result') {
displayResult(e.data.result, operation);
updateProgress(100);
}
};
processingWorker.postMessage({
type: 'process',
operation: operation,
data: currentData
});
}
// 更新进度
function updateProgress(progress) {
taskProgress.value = progress;
progressText.textContent = progress + '%';
}
// 显示结果
function displayResult(result, operation) {
let resultHtml = `<h3>${getOperationName(operation)}完成</h3>`;
switch (operation) {
case 'sort':
resultHtml += `
<p>排序耗时: ${result.duration}ms</p>
<p>排序算法: ${result.algorithm}</p>
<p>前5个值: ${result.preview.join(', ')}</p>
`;
break;
case 'filter':
resultHtml += `
<p>过滤耗时: ${result.duration}ms</p>
<p>原始数据: ${result.originalCount}</p>
<p>过滤后: ${result.filteredCount}</p>
<p>过滤率: ${result.filterRate}%</p>
`;
break;
case 'aggregate':
resultHtml += `
<p>聚合耗时: ${result.duration}ms</p>
<p>总和: ${result.sum}</p>
<p>平均值: ${result.average}</p>
<p>最大值: ${result.max}</p>
<p>最小值: ${result.min}</p>
`;
break;
case 'transform':
resultHtml += `
<p>转换耗时: ${result.duration}ms</p>
<p>转换类型: ${result.transformType}</p>
<p>处理记录: ${result.processedCount}</p>
`;
break;
}
resultsDisplay.innerHTML = resultHtml;
}
// 获取操作名称
function getOperationName(operation) {
const names = {
'sort': '数据排序',
'filter': '数据过滤',
'aggregate': '数据聚合',
'transform': '数据转换'
};
return names[operation] || '数据处理';
}
});
</script>
</body>
</html><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实时计算Worker</title>
</head>
<body>
<h1>实时计算Worker应用</h1>
<!-- 计算控制 -->
<section class="calculation-control">
<h2>计算控制</h2>
<div class="control-buttons">
<button id="start-calculation">开始计算</button>
<button id="pause-calculation">暂停计算</button>
<button id="stop-calculation">停止计算</button>
<button id="reset-calculation">重置计算</button>
</div>
<div class="calculation-settings">
<label>计算强度: <input type="range" id="intensity" min="1" max="10" value="5"></label>
<label>更新频率: <input type="range" id="frequency" min="1" max="60" value="30"> Hz</label>
</div>
</section>
<!-- 实时显示 -->
<section class="real-time-display">
<h2>实时数据</h2>
<div class="metrics-grid">
<div class="metric-card">
<h3>计算次数</h3>
<div class="metric-value" id="calculation-count">0</div>
</div>
<div class="metric-card">
<h3>计算速度</h3>
<div class="metric-value" id="calculation-speed">0 /s</div>
</div>
<div class="metric-card">
<h3>CPU使用率</h3>
<div class="metric-value" id="cpu-usage">0%</div>
</div>
<div class="metric-card">
<h3>内存使用</h3>
<div class="metric-value" id="memory-usage">0 MB</div>
</div>
</div>
</section>
<!-- 计算结果 -->
<section class="calculation-results">
<h2>计算结果</h2>
<div id="results-chart" role="img" aria-label="计算结果图表"></div>
<div id="results-data" role="region" aria-live="polite"></div>
</section>
<script>
// 实时计算Worker应用
document.addEventListener('DOMContentLoaded', function() {
const intensitySlider = document.getElementById('intensity');
const frequencySlider = document.getElementById('frequency');
const calculationCount = document.getElementById('calculation-count');
const calculationSpeed = document.getElementById('calculation-speed');
const cpuUsage = document.getElementById('cpu-usage');
const memoryUsage = document.getElementById('memory-usage');
const resultsChart = document.getElementById('results-chart');
const resultsData = document.getElementById('results-data');
let calculationWorker = null;
let isCalculating = false;
let startTime = null;
let totalCalculations = 0;
let resultsHistory = [];
// 控制按钮
document.getElementById('start-calculation').addEventListener('click', startCalculation);
document.getElementById('pause-calculation').addEventListener('click', pauseCalculation);
document.getElementById('stop-calculation').addEventListener('click', stopCalculation);
document.getElementById('reset-calculation').addEventListener('click', resetCalculation);
// 参数变化
intensitySlider.addEventListener('input', updateSettings);
frequencySlider.addEventListener('input', updateSettings);
// 开始计算
function startCalculation() {
if (isCalculating) return;
isCalculating = true;
startTime = Date.now();
if (calculationWorker) {
calculationWorker.terminate();
}
calculationWorker = new Worker('real-time-calculation-worker.js');
calculationWorker.onmessage = function(e) {
handleCalculationResult(e.data);
};
calculationWorker.postMessage({
type: 'start',
intensity: parseInt(intensitySlider.value),
frequency: parseInt(frequencySlider.value)
});
}
// 暂停计算
function pauseCalculation() {
if (!isCalculating) return;
isCalculating = false;
if (calculationWorker) {
calculationWorker.postMessage({
type: 'pause'
});
}
}
// 停止计算
function stopCalculation() {
isCalculating = false;
if (calculationWorker) {
calculationWorker.postMessage({
type: 'stop'
});
calculationWorker.terminate();
calculationWorker = null;
}
}
// 重置计算
function resetCalculation() {
stopCalculation();
totalCalculations = 0;
resultsHistory = [];
startTime = null;
updateDisplay();
resultsChart.innerHTML = '';
resultsData.innerHTML = '';
}
// 更新设置
function updateSettings() {
if (calculationWorker && isCalculating) {
calculationWorker.postMessage({
type: 'updateSettings',
intensity: parseInt(intensitySlider.value),
frequency: parseInt(frequencySlider.value)
});
}
}
// 处理计算结果
function handleCalculationResult(data) {
switch (data.type) {
case 'result':
totalCalculations++;
resultsHistory.push(data.result);
// 限制历史记录数量
if (resultsHistory.length > 100) {
resultsHistory.shift();
}
updateDisplay();
updateChart();
break;
case 'performance':
updatePerformanceMetrics(data.metrics);
break;
case 'error':
console.error('计算错误:', data.error);
break;
}
}
// 更新显示
function updateDisplay() {
calculationCount.textContent = totalCalculations.toLocaleString();
if (startTime) {
const elapsed = (Date.now() - startTime) / 1000;
const speed = totalCalculations / elapsed;
calculationSpeed.textContent = speed.toFixed(1) + ' /s';
}
if (resultsHistory.length > 0) {
const latest = resultsHistory[resultsHistory.length - 1];
resultsData.innerHTML = `
<h3>最新结果</h3>
<p>计算值: ${latest.value}</p>
<p>计算时间: ${latest.duration}ms</p>
<p>时间戳: ${new Date(latest.timestamp).toLocaleTimeString()}</p>
`;
}
}
// 更新图表
function updateChart() {
if (resultsHistory.length === 0) return;
const chartData = resultsHistory.slice(-50); // 显示最近50个点
const max = Math.max(...chartData.map(r => r.value));
const min = Math.min(...chartData.map(r => r.value));
let chartHtml = '<div class="chart-container">';
chartHtml += '<h3>计算结果趋势</h3>';
chartHtml += '<div class="chart-line">';
chartData.forEach((result, index) => {
const normalized = (result.value - min) / (max - min || 1);
const height = normalized * 100;
chartHtml += `<div class="chart-point" style="height: ${height}%" title="${result.value}"></div>`;
});
chartHtml += '</div>';
chartHtml += `<p>范围: ${min.toFixed(2)} - ${max.toFixed(2)}</p>`;
chartHtml += '</div>';
resultsChart.innerHTML = chartHtml;
}
// 更新性能指标
function updatePerformanceMetrics(metrics) {
cpuUsage.textContent = metrics.cpuUsage + '%';
memoryUsage.textContent = (metrics.memoryUsage / 1024 / 1024).toFixed(2) + ' MB';
}
});
</script>
</body>
</html>A1: Worker可以访问大部分Web API,但不能访问DOM、父对象的属性和某些特定的API。可以访问XMLHttpRequest、WebSockets、IndexedDB等。
A2: 使用批处理技术,将大数据分块处理,定期向主线程报告进度,避免内存溢出。
A3: Worker在创建后开始运行,可以通过terminate()方法终止,或者在Worker脚本执行完毕后自动结束。
A4: 使用浏览器开发者工具的Sources面板,可以在Worker脚本中设置断点进行调试。
A5: 创建Worker有一定开销,但对于CPU密集型任务,性能收益通常远大于开销。
通过本节的学习,您应该能够熟练使用Web Workers创建高性能的多线程应用,优化用户体验,处理复杂的计算任务。