Javascript-暂停执行,直到标志变为true

Javascript-暂停执行,直到标志变为true,javascript,jquery,synchronization,sync,wait,Javascript,Jquery,Synchronization,Sync,Wait,如何暂停javascript执行,直到标志变为真 例如,我有这样一条xml消息: [...] <action> <resource update>id</resourceupdate> </action> <action> <event>id1</event> </action> <action> <event>id2</event> <

如何暂停javascript执行,直到标志变为真

例如,我有这样一条xml消息:

[...]
<action>
    <resource update>id</resourceupdate>
</action>
<action>
    <event>id1</event>
</action>
<action>
    <event>id2</event>
</action>
<action>
    <event>id3</event>
</action>
[...]
function browserLoaded() {
  if (!ready) {
    // note the missing "()"
    setTimeout(browserLoaded, 1000);
  }
} 
//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()
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;
})
等待功能是:

function browserLoaded() {
if (!ready) {
    setTimeout(browserLoaded(),1000);
}
} 
当加载iframe时,ready var变为true:

$(iframe).load(function() {
    ready = true;
});
但当执行时,我将捕获此错误:

 Maximum call stack size exceeded error
有什么想法吗?
谢谢

问题出在这个函数中,它调用自己直到堆栈满:

function browserLoaded() {
  if (!ready) {
    //here you call browserLoaded function instead of passing a reference to the function
    setTimeout(browserLoaded() ,1000);
  }
} 
您的函数应该如下所示:

[...]
<action>
    <resource update>id</resourceupdate>
</action>
<action>
    <event>id1</event>
</action>
<action>
    <event>id2</event>
</action>
<action>
    <event>id3</event>
</action>
[...]
function browserLoaded() {
  if (!ready) {
    // note the missing "()"
    setTimeout(browserLoaded, 1000);
  }
} 
//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()
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;
})

这是一个糟糕的设计。您不需要“等待”超时机制。如果您是通过jqueryajax请求加载页面,请使用回调函数继续执行代码(您也许可以跟踪正在处理的“当前”项并继续执行下一个)。如果您正在加载iFrame,这也是一个糟糕的设计,那么您应该转向jQuery ajax方式。

一个快速的技巧就是设置一个轮询循环:使用setInterval每隔一段时间检查一次变量是否已设置,然后使用clearInterval并在指定时间继续执行

不管怎样,做事都会很痛苦。本质上,用Javascript告诉某些东西运行后者的唯一方法是将其打包到函数中。但这样做之后,它会变得更容易,因为您可以传递该函数,并在完成后让异步代码调用它

例如,您的处理可能如下所示:

[...]
<action>
    <resource update>id</resourceupdate>
</action>
<action>
    <event>id1</event>
</action>
<action>
    <event>id2</event>
</action>
<action>
    <event>id3</event>
</action>
[...]
function browserLoaded() {
  if (!ready) {
    // note the missing "()"
    setTimeout(browserLoaded, 1000);
  }
} 
//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()
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;
})
//这是一个简单的“信号量”模式:
var things\u to\u load\u count=1
var check_if_done(){
东西要装多少;

如果(things\u to\u load\u count使用某种标志确实是个坏主意。您必须使用延迟模式。类似于以下内容:

[...]
<action>
    <resource update>id</resourceupdate>
</action>
<action>
    <event>id1</event>
</action>
<action>
    <event>id2</event>
</action>
<action>
    <event>id3</event>
</action>
[...]
function browserLoaded() {
  if (!ready) {
    // note the missing "()"
    setTimeout(browserLoaded, 1000);
  }
} 
//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()
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;
})

p.S.

您确定在iframe加载函数中设置为true的ready变量与在调用另一个settimeout之前检查的变量相同。似乎iframe加载函数中的一个是局部变量,另一个是全局变量


或者两个就绪变量都是本地变量。

setTimeout(browserLoaded(),1000);
执行您的函数。您只需引用您的函数;删除
()
,使其成为
setTimeout(browserLoaded,1000)
感谢您的快速响应!好的,没有更多错误,但执行不会停止。我大大简化了代码,使其不包含不必要的信息。实际上,iframe的load函数包含多个处理程序,用于截获用户交互并将xml消息发送到servlet。这将存储这些消息,并或多或少地将它们发送给其他客户端用异步回调函数Get on through的语法表示(简化)我不能在iframe加载的回调中处理消息,因为这些消息是异步的,不一定到达加载iframehm,你不能至少利用iframe的onLoad事件吗?不处理消息,但最多触发一个变量(ready):(如果你能触发一个变量(在iFrame的父级中)还应该能够调用函数。例如:[iFrame onLoad='parent.continueWithNextOne();']这难道不可能吗?如果iframe和父级在同一个域中,这应该是可能的?我不确定消息是否按此顺序到达,它可能会变得更公平。我认为这样的设计是不好的。同样地编写两个代码分支。上面解释的情况是一个特殊情况,我不会推翻特定情况下的代码有趣的是,我会看一看这是正确的答案;代码并不完全是我所需要的,但是关于延迟的建议让我找到了解决问题的最佳解决方案。thanksi declare var ready=true在我的core.js开头(在任何分支或函数之外);在我只做了赋值之后,从不在其他地方声明变量。