使用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);
};
};
复制代码
参考: