Worker 使用
Web Worker
基础使用
// 判断浏览器是否支持 Worker
typeof Worker !== "undefined";
// 从脚本中创建 Worker
new Worker("workers.js");
// 使用字符串方式创建 Worker
new Worker("data:text/javascript;charset=US-ASCII,...");
worker-loader
worker-loader 是一个
import Worker from "worker-loader!./file.worker.js";
const worker = new Worker();
// 转化为下述代码
const blob = new Blob([codeFromFileWorker], { type: "application/javascript" });
const worker = new Worker(URL.createObjectURL(blob));
Blob
我们也可以自己通过
const code = `
importScripts('https://xxx.com/xxx.js');
self.onmessage = e => {};
`;
const blob = new Blob([code], { type: "application/javascript" });
const worker = new Worker(URL.createObjectURL(blob));
网络请求
By default, cookies are not included with fetch requests, but you can include them as follows: fetch(url, {credentials: ‘include’}).
function XHRWorker(url, ready, scope) {
var oReq = new XMLHttpRequest();
oReq.addEventListener(
"load",
function() {
var worker = new Worker(
window.URL.createObjectURL(new Blob([this.responseText]))
);
if (ready) {
ready.call(scope, worker);
}
},
oReq
);
oReq.open("get", url, true);
oReq.send();
}
function WorkerStart() {
XHRWorker(
"http://static.xxx.com/js/worker.js",
function(worker) {
worker.postMessage("hello world");
worker.onmessage = function(e) {
console.log(e.data);
};
},
this
);
}
WorkerStart();
跨线程消息
开启新的线程伴随而来的问题就是通讯问题。
postMessage
创建完毕之后,我们主要依靠
// worker.js
// 向主线程发送消息
postMessage("event from worker");
// 接收来自主线程的消息
onmessage = function(event) {};
// UI
worker.onmessage = function(event) {};
worker.postMessage("event from ui");
// 关闭当前 worker
worker.terminate();
主线程与
// main
var worker = new Worker("./worker.js");
worker.onmessage = function getMessageFromWorker(e) {
// 被改造后的数据,与原数据对比,表明数据是被克隆了一份
console.log("e.data", " -- ", e.data);
// [2, 3, 4]
// msg 依旧是原本的 msg,没有任何改变
console.log("msg", " -- ", msg);
// [1, 2, 3]
};
var msg = [1, 2, 3];
worker.postMessage(msg);
// worker
onmessage = function(e) {
var newData = increaseData(e.data);
postMessage(newData);
};
function increaseData(data) {
for (let i = 0; i < data.length; i++) {
data[i] += 1;
}
return data;
}
由上述代码可知,每一个消息内的数据在不同的线程中,都是被克隆一份以后再传输的。数据量越大,数据传输速度越慢。
sharedBufferArray
对象转移使用方式很简单,给
var ab = new ArrayBuffer(1);
worker.postMessage(ab, [ab]);
// main.js
var worker = new Worker("./sharedArrayBufferWorker.js");
worker.onmessage = function(e) {
// 传回到主线程已经被计算过的数据
console.log("e.data", " -- ", e.data);
// SharedArrayBuffer(3) {}
// 和传统的 postMessage 方式对比,发现主线程的原始数据发生了改变
console.log("int8Array-outer", " -- ", int8Array);
// Int8Array(3) [2, 3, 4]
};
var sharedArrayBuffer = new SharedArrayBuffer(3);
var int8Array = new Int8Array(sharedArrayBuffer);
int8Array[0] = 1;
int8Array[1] = 2;
int8Array[2] = 3;
worker.postMessage(sharedArrayBuffer);
// worker.js
onmessage = function(e) {
var arrayData = increaseData(e.data);
postMessage(arrayData);
};
function increaseData(arrayData) {
var int8Array = new Int8Array(arrayData);
for (let i = 0; i < int8Array.length; i++) {
int8Array[i] += 1;
}
return arrayData;
}
通过共享内存传递的数据,在