如何暂停javascript执行,直到标志变为真?
例如,我有一个像这样的xml消息:
[...]
<action>
<resource update>id</resourceupdate>
</action>
<action>
<event>id1</event>
</action>
<action>
<event>id2</event>
</action>
<action>
<event>id3</event>
</action>
[...]
我希望仅在处理节点resourceupdate之后处理事件节点(这需要更多时间来提供服务,因为它需要加载页面):
在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
}
});
等待功能是:
function browserLoaded() {
if (!ready) {
setTimeout(browserLoaded(),1000);
}
}
,当加载iframe时,ready var变为true:
$(iframe).load(function() {
ready = true;
});
但是当执行时我会发现这个错误:
Maximum call stack size exceeded error
任何想法? 谢谢!
答案 0 :(得分:0)
问题在于这个函数调用自己直到堆栈已满:
function browserLoaded() {
if (!ready) {
//here you call browserLoaded function instead of passing a reference to the function
setTimeout(browserLoaded() ,1000);
}
}
您的功能应如下所示:
function browserLoaded() {
if (!ready) {
// note the missing "()"
setTimeout(browserLoaded, 1000);
}
}
答案 1 :(得分:0)
这是一个糟糕的设计。您不需要“等待”超时机制。如果您通过jQuery ajax请求加载页面,请使用回调函数继续执行代码(您可以跟踪正在处理的“当前”项目并继续下一个)。如果你正在加载iFrames,那也是糟糕的设计,你应该转向jQuery ajax方式。
答案 2 :(得分:0)
使用某种旗帜真是个坏主意。您必须使用延迟模式。像这样:
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;
})
答案 3 :(得分:0)
您确定在iframe加载函数中设置为true的ready变量与在调用另一个settimeout之前检查的变量相同。似乎iframe加载函数中的一个是局部变量而另一个是全局变量。
或两个就绪变量都是本地变量。
答案 4 :(得分:-1)
你可以做的一个快速入侵就是设置一个轮询循环:使用setInterval每隔一段时间检查一次是否已设置变量和clearInterval并在其时间继续执行。
无论如何,做事情会很痛苦。从本质上讲,告诉Javascript运行后者的唯一方法是将其打包到函数中。执行此操作之后,它变得更容易,因为您可以传递该函数并在完成后让异步代码调用它。例如,您的处理可能如下所示:
//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()