使用本地文件创建Web Worker多线程任务,分担复杂的操作,加快操作速度
使用场景:批量下载
一、Web Worker
web worker 是运行在后台的 JavaScript,不会影响页面的性能。
当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。
web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。您可以继续做任何愿意做的事情:点击、选取内容等等,而此时 web worker 在后台运行。
在创建 web worker 之前,请检测用户的浏览器是否支持它:
if(typeof(Worker)!==“undefined”) { // Yes! Web worker support! // Some code… } else { // Sorry! No Web Worker support… }
二、使用步骤
1.创建worker
html
<div id="worker">{{textContent}}</div>
data
data() {
return {
textContent: `let i = 0;
function timedCount() {
for (let x = 0; x < 1; x++) {
i = i + 1;
postMessage(i);
}
setTimeout('timedCount()', 500);
};
timedCount();`,
};
},
2.调用worker
const urlObject = window.URL || window.webkitURL || window;
const blob = new Blob([document.getElementById("worker").textContent]);
const url = urlObject.createObjectURL(blob);
const myworker1 = new Worker(url);
// web worker 的onmessage方法是异步操作
myworker1.onmessage = (e) => {
debugger;
myworker1.terminate();
myworker1 = undefined;
};
3.同页面的 Web Worker
必须指定
<!DOCTYPE html>
<body>
<script id="worker" type="app/worker">
addEventListener('message', function () {
postMessage('some message');
}, false);
</script>
</body>
</html>
var blob = new Blob([document.querySelector('#worker').textContent]);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);
worker.onmessage = function (e) {
// e.data === 'some message'
};
4.API
主线程
主线程生成 Worker 线程
var myWorker = new Worker(jsUrl, options);
Worker()构造函数,可以接受两个参数。第一个参数是脚本的网址(必须遵守同源政策),该参数是必需的,且只能加载 JS 脚本,否则会报错。第二个参数是配置对象,该对象可选。它的一个作用就是指定 Worker 的名称,用来区分多个 Worker 线程。
// 主线程
var myWorker = new Worker('worker.js', { name : 'myWorker' });
// Worker 线程
self.name // myWorker
Worker()构造函数返回一个 Worker 线程对象,用来供主线程操作 Worker。
- Worker.onerror:指定 error 事件的监听函数。
- Worker.onmessage:指定 message 事件的监听函数,发送过来的数据在Event.data属性中。
- Worker.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
- Worker.postMessage():向 Worker 线程发送消息。
- Worker.terminate():立即终止 Worker 线程。
worker线程
Web Worker 有自己的全局对象,不是主线程的window,而是一个专门为 Worker 定制的全局对象。
- self.name: Worker 的名字。该属性只读,由构造函数指定。
- self.onmessage:指定message事件的监听函数。
- self.onmessageerror:指定 messageerror 事件的监听函数。发送的数据无法序列化成字符串时,会触发这个事件。
- self.close():关闭 Worker 线程。
- self.postMessage():向产生这个 Worker 线程发送消息。
- self.importScripts():加载 JS 脚本。
5.实例:Worker 线程完成轮询
function createWorker(f) {
var blob = new Blob(['(' + f.toString() +')()']);
var url = window.URL.createObjectURL(blob);
var worker = new Worker(url);
return worker;
}
var pollingWorker = createWorker(function (e) {
var cache;
function compare(new, old) { ... };
setInterval(function () {
fetch('/my-api-endpoint').then(function (res) {
var data = res.json();
if (!compare(data, cache)) {
cache = data;
self.postMessage(data);
}
})
}, 1000)
});
pollingWorker.onmessage = function () {
// render data
}
pollingWorker.postMessage('init');
worker的方法
接受消息
主线程接受worker的消息
// 主线程
worker.onmessage = function (event) {
console.log('Received message ' + event.data);
doSomething();
}
function doSomething() {
// 执行任务
worker.postMessage('Work done!');
}
// Worker 线程
self.addEventListener('message', function (e) {
self.postMessage('You said: ' + e.data);
}, false);
self.onmessage = function (e) {
var uInt8Array = e.data;
postMessage('Inside worker.js: uInt8Array.toString() = ' + uInt8Array.toString());
postMessage('Inside worker.js: uInt8Array.byteLength = ' + uInt8Array.byteLength);
};
发送消息
// 主线程
worker.postMessage('Hello World');
worker.postMessage({method: 'echo', args: ['Work']});
// Worker 线程
self.postMessage('WORKER STOPPED: ' + data.msg);
关闭 Worker
// 主线程
worker.terminate();
// Worker 线程
self.close();
Worker 加载脚本
// Worker 线程
importScripts('script1.js', 'script2.js');
错误处理
// 主线程
worker.onerror(function (event) {
console.log([
'ERROR: Line ', e.lineno, ' in ', e.filename, ': ', e.message
].join(''));
});
// 或者
worker.addEventListener('error', function (event) {
// ...
});