使用Web Worker可以在后台线程中运行 JavaScript,线程可以执行任务而不会干扰用户界面。
使用规则
worker是使用Worker()构造出的实例对象,在后台线程中运行一个命名的 JavaScript 脚本。worker实例对象可以通过将信息发送到创建它的 JavaScript 代码。worker运行在另一个全局上下文中,而非window对象。worker中不能直接操作 DOM 节点,也不能使用window对象的默认方法和属性。worker和主线程之间,通过postMessage()方法发送各自的数据,使用onmessage事件处理函数来响应数据,数据在message事件的data属性中。worker和主线程之间传递的数据是另外复制的数据。- 主线程可以使用实例对象上的
terminate()方法立刻终止该worker。 worker线程内部可以使用close()关闭自身。worker的一个优势在于能够执行处理器密集型的运算而不会阻塞 UI 线程。
应用举例
如下代码所示,在主线程中首先进行了兼容性检验,创建了一个由worker.js执行的Worker。通过myWorker.postMessage()发送消息。通过myWorker.onmessage响应Worker返回的消息。
const a = 1;
const b = 2;
if (window.Worker) {
const myWorker = new Worker('./worker.js');
myWorker.postMessage({ a, b });
myWorker.onmessage = e => {
console.log('收到worker的信息...');
console.log(e.data);
};
}
在Worker中,通过onmessage响应主线程发送的消息,经过一些处理后,通过postMessage返回消息到主线程。
// worker.js
onmessage = e => {
console.log('收到主线程的信息...');
const { a, b } = e.data;
const sum = a + b;
postMessage(sum);
};
从这里我们可以看到,主线程中,onmessage和postMessage()必须挂在worker对象上。而在worker内部,不必这样做,因为worker有自己的作用域。
如下代码所示,在worker的onmessage中打印this:
onmessage = e => {
console.log(this);
};

终止 worker
在上述代码中,若在主线程中调用myWorker.terminate(),则不会收到任何消息,因为worker线程刚创建完毕就被终止。
const a = 1;
const b = 2;
if (window.Worker) {
const myWorker = new Worker('./worker.js');
myWorker.postMessage({ a, b });
// 终止myWorker
myWorker.terminate();
myWorker.onmessage = e => {
console.log('收到worker的信息...');
console.log(e.data);
};
}
同样,在worker线程中调用close(),主线程也不会有任何响应,因为线程刚启动就被关闭。
close();
onmessage = e => {
console.log('收到主线程的信息...');
const { a, b } = e.data;
const sum = a + b;
postMessage(sum);
};
共享 worker
主线程:
const a = 1;
const b = 2;
if (window.Worker) {
const myWorker = new SharedWorker('./worker.js');
myWorker.port.postMessage({ a, b });
myWorker.port.onmessage = e => {
console.log('收到worker的信息...');
console.log(e.data);
};
}
worker线程:
onconnect = e => {
const port = e.ports[0];
port.onmessage = e => {
const { a, b } = e.data;
const sum = a + b;
port.postMessage(sum);
};
};










