Знать, когда все асинхронные вызовы, инициированные .each (), выполнены - PullRequest
0 голосов
/ 13 января 2012

Я что-то строю с помощью node.js и перебираю все теги img с помощью jQuery .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 ]

4 голосов
/ 13 января 2012

ВЫ НЕ МОЖЕТЕ ВОЗВРАЩАТЬ ЗНАЧЕНИЯ ИЗ ФУНКЦИЙ, КОТОРЫЕ ЗАВИСИТ ОТ РЕЗУЛЬТАТА АСИНХРОННЫХ ЗВОНКОВ

Извините за крик, но нужно было сказать ...

лучшее, что вы можете сделать, - это вызвать еще один обратный вызов, как только все остальные будут выполнены.

Все остальное приведет к занятым циклам, что сделает приложение не реагирующим.

Чтобы решить эту проблему (без каламбура), используйте объекты deferred jQuery:

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 с результатомокончательный расчет.

0 голосов
/ 13 января 2012

Попробуйте это:

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 для завершения задачи.

0 голосов
/ 13 января 2012

Попробуйте это ...

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...