我做了一个HTML表单,在很多不同的选项卡中有很多问题(来自数据库).然后用户在这些问题中给出答案.每次用户更改选项卡时,我的Javascript都会创建一个保存.问题是每次更改选项卡时我都必须遍历所有问题,并且每次冻结表单大约5秒钟.
我一直在寻找答案如何在后台运行我的保存功能.显然没有真正的方法在后台运行某些东西,很多人建议使用setTimeout();例如这一个如何让一组js函数在后台运行
但是这些例子都没有解释或考虑到即使我使用类似的东西setTimeout(saveFunction, 2000);也无法解决我的问题.在这种情况下,它只将它推迟2秒.
有没有办法解决这个问题?
Don*_*uck 20
您可以使用网络工作者。这里的一些旧答案说它们没有得到广泛支持(我猜在编写这些答案时它们还没有得到广泛支持),但今天它们受到所有主要浏览器的支持。
要运行 Web Worker,您需要创建内置Worker类的实例。构造函数采用一个参数,该参数是包含要在后台运行的代码的 javascript 文件的 URI。例如:
let worker = new Worker("/path/to/script.js");
Run Code Online (Sandbox Code Playgroud)
Web Worker 受同源策略的约束,因此如果您传递这样的路径,目标脚本必须与调用它的页面位于同一域中。
如果您不想为此创建新的 Javascript 文件,您还可以使用数据 URI:
let worker = new Worker(
`data:text/javascript,
//Enter Javascript code here
`
);
Run Code Online (Sandbox Code Playgroud)
由于同源策略,您无法从数据 URI 发送 AJAX 请求,因此如果您需要在 Web Worker 中发送 AJAX 请求,则必须使用单独的 Javascript 文件。
您指定的代码(在单独的文件中或在数据 URI 中)将在您调用Worker构造函数后立即运行。
不幸的是,Web Worker 既无法访问外部 Javascript 变量、函数或类,也无法访问 DOM,但您可以通过使用方法postMessage和onmessage事件来解决这个问题。在外部代码中,这些是工作对象的成员(worker在上面的示例中),而在工作人员内部,这些是全局上下文的成员(因此可以通过使用来调用它们this,或者就像前面没有任何内容一样)。
postMessage并且onmessage双向工作,因此当worker.postMessage在外部代码中调用时,onmessage会在工作线程中触发,而当postMessage在工作线程中调用时,worker.onmessage会在外部代码中触发。
postMessage接受一个参数,这是您想要传递的变量(但您可以通过传递数组来传递多个变量)。不幸的是,函数和 DOM 元素无法传递,当你尝试传递一个对象时,只会传递它的属性,而不是它的方法。
onmessage接受一个参数,该参数是一个MessageEvent对象。该MessageEvent对象有一个data属性,其中包含使用第一个参数发送的数据postMessage。
这是使用网络工作者的示例。在此示例中,我们有一个函数 ,functionThatTakesLongTime它接受一个参数并根据该参数返回一个值,并且我们希望使用 Web Workers 以便在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).
Run Code Online (Sandbox Code Playgroud)
显然没有真正的方法在背景上运行某些东西......
在大多数现代浏览器上(但不是IE9和更早版本):Web Workers.
但我认为你正在试图解决在错误级别的问题:1.应该在一个可以遍历所有控件的很多不到五秒钟,2.它不应该是必要通过所有循环只控制其中一个更改时控制.
我建议在尝试将处理卸载到后台之前查看这些问题.
例如,您可以拥有一个包含每个项目当前值的对象,然后让每个项目的UI在值更改时更新该对象.然后,您将拥有该对象中的所有值,而无需再次遍历所有控件.
| 归档时间: |
|
| 查看次数: |
31900 次 |
| 最近记录: |