0

如何在标志变为真之前暂停 javascript 执行?

例如,我有这样的 xml 消息:

[...]
<action>
    <resource update>id</resourceupdate>
</action>
<action>
    <event>id1</event>
</action>
<action>
    <event>id2</event>
</action>
<action>
    <event>id3</event>
</action>
[...]

我希望仅在处理节点资源更新之后才处理事件节点(这需要更多时间来提供服务,因为它需要加载页面):

在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

有任何想法吗?谢谢!

4

5 回答 5

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);
  }
} 
于 2012-12-17T21:50:24.087 回答
0

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

于 2012-12-17T21:52:32.457 回答
0

您可以做的一个快速破解就是设置一个轮询循环:使用 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()
于 2012-12-17T22:03:16.583 回答
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;
})

PShttp ://api.jquery.com/category/deferred-object/

于 2012-12-17T22:12:09.780 回答
0

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

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

于 2012-12-17T22:21:33.580 回答