您可以使用网络工作者。这里的一些较旧的答案说它们没有得到广泛的支持(我猜在编写这些答案时没有得到广泛的支持),但今天它们得到了所有主要浏览器的支持。
要运行 Web Worker,您需要创建内置Worker类的实例。构造函数采用一个参数,即包含您要在后台运行的代码的 javascript 文件的 URI。例如:
let worker = new Worker("/path/to/script.js");
Web Worker 遵循同源策略,因此如果您传递这样的路径,则目标脚本必须与调用它的页面位于同一域中。
如果您不想为此创建新的 Javascript 文件,也可以使用数据 URI:
let worker = new Worker(
`data:text/javascript,
//Enter Javascript code here
`
);
由于同源策略,不能从数据 URI 发送 AJAX 请求,因此如果需要在 web worker 中发送 AJAX 请求,则必须使用单独的 Javascript 文件。
您指定的代码(在单独的文件中或在数据 URI 中)将在您调用Worker构造函数后立即运行。
不幸的是,web worker 既不能访问外部的 Javascript 变量、函数或类,也不能访问 DOM,但是你可以通过使用postMessage方法和onmessage事件来解决这个问题。在外部代码中,这些是 worker 对象的成员(worker在上面的示例中),而在 worker 内部,这些是全局上下文的成员(因此可以通过 usingthis或在前面没有任何内容的方式调用它们)。
postMessage并且onmessage双向工作,所以当worker.postMessage在外部代码中调用时,在工作人员中被解雇onmessage,在工作人员中postMessage被调用时,worker.onmessage在外部代码中被解雇。
postMessage接受一个参数,即您要传递的变量(但您可以通过传递数组来传递多个变量)。不幸的是,函数和 DOM 元素不能被传递,当你试图传递一个对象时,只会传递它的属性,而不是它的方法。
onmessage接受一个参数,它是一个MessageEvent对象。该MessageEvent对象有一个data属性,其中包含使用 的第一个参数发送的数据postMessage。
这是一个使用网络工作者的例子。在这个例子中,我们有一个函数 ,functionThatTakesLongTime它接受一个参数并根据该参数返回一个值,我们希望使用 web worker 来在functionThatTakesLongTime(foo)不冻结 UI 的情况下查找foo,外部代码中的某个变量在哪里。
let worker = new Worker(
`data:text/javascript,
function functionThatTakesLongTime(someArgument){
//There are obviously faster ways to do this, I made this function slow on purpose just for the example.
for(let i = 0; i < 1000000000; i++){
someArgument++;
}
return someArgument;
}
onmessage = function(event){ //This will be called when worker.postMessage is called in the outside code.
let foo = event.data; //Get the argument that was passed from the outside code, in this case foo.
let result = functionThatTakesLongTime(foo); //Find the result. This will take long time but it doesn't matter since it's called in the worker.
postMessage(result); //Send the result to the outside code.
};
`
);
worker.onmessage = function(event){ //Get the result from the worker. This code will be called when postMessage is called in the worker.
alert("The result is " + event.data);
}
worker.postMessage(foo); //Send foo to the worker (here foo is just some variable that was defined somewhere previously).