知道.each()启动的所有异步调用何时完成执行

时间:2012-01-12 22:43:44

标签: javascript jquery node.js asynchronous callback

我正在使用node.js构建一些东西,并且我使用jQuery img循环遍历所有.each()标记。完成所有回调.each()修正后,我将在foo中获得所需的价值。

var foo = -1;
window.each(function() {
  // abracadabra
  if (baz) foo = bar;
});
return foo; // this returns the incorrect foo as not all callbacks are complete

我该如何解决这个问题?

修改

一种方法是使用无限循环来持续检查回调的数量,并且当所有回调完成后返回foo。我觉得这有点黑客,会有更好的东西吗?

var allCallbacksDone = false;
var foo = -1;
window.each(function(index, element) {
  // abracadabra
  if (baz) foo = bar;
  if (index == window.length - 1) allCallbacksDone = true;
});
while (!allCallbacksDone) {
  continue;
}
return foo;

第二次编辑

abracadabra是下载非同步远程图像的GET请求。

3 个答案:

答案 0 :(得分:4)

您不能从依赖于异步呼叫的功能中返回值

对于喊叫感到抱歉,但不得不说......

您可以做的最好的事情就是在完成所有其他操作后调用另一个回调。

其他任何东西都会导致繁忙的循环。这将使应用程序无响应。

要解决此问题(无双关语),请使用jQuery的deferred对象:

var defArray = [];

window.each(function(index, element) {

    // create a deferred object and store it
    var d = $.Deferred();
    defArray.push(d);

    // trigger the image download 
    however you do it...

    // register a callback for the download completion
    // which "resolves" the deferred object
    someimg.onload = function() {
        d.resolve();

        // probably other actions needed here too
    }        
});

// now call _another_ function once _all_ of the deferreds are resolved
$.when.apply($, defArray).then(function() {
    // everything is done - do your calculations
});

请注意,我的第一行仍然存在 - 您不能只等待所有内容然后返回结果 - JS不会那样工作。

理想情况下,您将创建一个添加的延迟对象,并且您的函数会根据该对象返回promise,最终回调将resolve与最终计算结果。

答案 1 :(得分:0)

试试这个......

var foo = -1;  // Don't need this now
var count = window.length;
window.each(function() {
  // abracadabra
  count--;
  if (count == 0) complete(bar);
});

function complete(value) {
//  everything is complete and value == bar
}

答案 2 :(得分:0)

试试这个:

function check(callback) {
  var foo = -1, complete = false, count = window.length - 1, interval;
  window.each(function (index) {
    if (baz) foo = bar;
    complete = (index == count);
  });
  interval = setInterval(function () {
    if (complete) {
      clearInterval(interval);
      callback();
    }
  }, 20);
}

致电check()以运行.each()循环,为任务完成时提供callback方法。