Javascript - 暂停执行直到标志变为真
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13922656/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript - pause execution until flag becomes true
提问by jenjis
how can i pause a javascript execution until a flag becomes true?
如何暂停 javascript 执行,直到标志变为真?
For Example, i've a xml message like this:
例如,我有一条这样的 xml 消息:
[...]
<action>
<resource update>id</resourceupdate>
</action>
<action>
<event>id1</event>
</action>
<action>
<event>id2</event>
</action>
<action>
<event>id3</event>
</action>
[...]
I wish that the event nodes are processed only after processing node resourceupdate (which requires more time to be served, as it requires the loading of a page):
我希望事件节点仅在处理节点资源更新后才被处理(这需要更多的时间来提供服务,因为它需要加载一个页面):
in javascript to process this message with an iterator (each) i've tried:
在 javascript 中使用迭代器(每个)处理此消息,我尝试过:
$(_response).find('ACTION').each(function() {
if (tagName=="RESOURCEUPDATE") {
ready = false;
//load the resource with selected id in an iframe
} else if (tagName=="EVENT") {
browserLoaded(); //the waiting function
eventhandler(); //consume the event
}
});
the waiting function is:
等待函数是:
function browserLoaded() {
if (!ready) {
setTimeout(browserLoaded(),1000);
}
}
and the ready var becomes true when the iframe is loaded:
加载 iframe 时,就绪变量变为真:
$(iframe).load(function() {
ready = true;
});
but when execute i'll catch this error:
但是当执行时我会发现这个错误:
Maximum call stack size exceeded error
any ideas? thanks!
有任何想法吗?谢谢!
采纳答案by Sergii Stotskyi
It's really a bad idea to use some kind of a flag. You have to use Deferred Pattern. Something like this:
使用某种标志真的是一个坏主意。您必须使用延迟模式。像这样的东西:
var resources = [];
$(_response).find('ACTION').each(function() {
var deferred = resources.length > 0 ? resources[resources.length - 1] : null;
switch (tagName) {
case "RESOURCEUPDATE":
deferred = $.Deferred();
//load the resource with selected id in an iframe
$(iframe).bind('load', function () {
deferred.resolve(/*specific arg1, arg2, arg3, ...*/)
});
resources.push(deferred);
break;
case "EVENT":
if (deferred) {
deferred.done(function (/*specific arg1, arg2, arg3, ...*/) {
// process event node
});
}
break;
}
});
// clean up deferreds objects when all them will be processed
$.when.apply($, resources).then(function() {
resources.length = 0;
})
回答by Andreas K?berle
The problem is in this function which call itself until the stack is full:
问题出在这个函数中,它会调用自己直到堆栈已满:
function browserLoaded() {
if (!ready) {
//here you call browserLoaded function instead of passing a reference to the function
setTimeout(browserLoaded() ,1000);
}
}
Your function should look like this:
您的函数应如下所示:
function browserLoaded() {
if (!ready) {
// note the missing "()"
setTimeout(browserLoaded, 1000);
}
}
回答by hyankov
This is a terrible design. You don't need the 'waiting' timeout mechanism. If you are loading the pages via jQuery ajax request, make use of the callback functions to continue with your code execution (you can perhaps keep track of the 'current' item being processed and continue with the next). If you are loading iFrames, that's bad design too, you should move to the jQuery ajax way.
这是一个可怕的设计。您不需要“等待”超时机制。如果您通过 jQuery ajax 请求加载页面,请使用回调函数继续您的代码执行(您或许可以跟踪正在处理的“当前”项目并继续下一个)。如果您正在加载 iFrame,那也是糟糕的设计,您应该转向 jQuery ajax 方式。
回答by hugomg
One quick hack that you could do is just set up a polling loop: use setInterval to check every once in a while if the variable has been set and clearInterval and continue execution when its time.
您可以做的一个快速技巧就是设置一个轮询循环:使用 setInterval 每隔一段时间检查一次变量是否已设置,然后 clearInterval 并在合适的时候继续执行。
Any way, its going to be a pain to do things. Essentially, the only way to tell something in Javascript to run latter is to package it inside a function. After you do this it gets easier though, since you can pass that function around and have the async code call it back when you are done.
无论如何,做事都会很痛苦。本质上,让 Javascript 中的某些东西在后面运行的唯一方法是将它打包到一个函数中。执行此操作后,它会变得更容易,因为您可以传递该函数并在完成后让异步代码回调它。
For example, your processing might look something like this:
例如,您的处理可能如下所示:
//this is a simple "semaphore" pattern:
var things_to_load_count = 1
var check_if_done(){
things_to_load_count--;
if(things_to_load_count <= 0){
//code to do stuff after you finish loading
}
};
$(_response).find('ACTION').each(function() {
if (tagName=="RESOURCEUPDATE") {
things_to_load_count++;
run_code_to_load_stuff( check_if_done )
//make sure that the run_code_to_load_stuff function
//calls the callback you passed it once its done.
} else if (tagName=="EVENT") {
//process one of the normal nodes
}
});
//this will run the remaining code if we loaded everything
//but will do nothing if we are still waiting.
check_if_done()
回答by Walter Brand
Are you sure that the ready variable that set true in the iframe load function is the same as the one that is checked before another settimeout is called. It seems that the one in the iframe load function is a local variable and the other one a global variable.
您确定在 iframe 加载函数中设置为 true 的就绪变量与调用另一个 settimeout 之前检查的变量相同吗?似乎 iframe 加载函数中的一个是局部变量,另一个是全局变量。
Or both ready variables are local.
或者两个就绪变量都是本地的。