2015-06-23 5 views
1

Я использую

$.when.apply($, arrayOfDeferreds).then(function() { 
    var args = Array.prototype.slice.call(arguments); 
    var anotherArrayOfDeferreds = []; 

    args.map(function(item){ 
     anotherArrayOfDeferreds.push(item.getSomething()); // item.getSomething() returns an deferred. 
    }); 

    // return an anotherArrayOfDeferreds 
}); 

иметь дело с массивом deferreds. Однако, в (сделайте что-то здесь ...) выше, он генерирует еще один массив отложенных, который по существу нуждается в другом $ .when.apply() и который не может быть обработан .then(). Мне интересно, есть ли способ связать $ .when?

Спасибо!

+0

_ "он создает еще один массив deferreds, который по существу нуждается еще $ .when.apply(), и которые не могут быть решены с помощью .then()" _ Можно создать stacksnippets, jsfiddle http://jsfiddle.net, чтобы продемонстрировать? – guest271314

ответ

1

Я думаю, что вы можете передать его снова $.when создать новое обещание, которое может быть возвращено из then, чтобы сделать его змеевидным

$.when.apply($, array).then(function() { 
    var newarray = []; 

    return $.when.apply($, newarray) 
}); 
+0

Я пробовал это. Но ... return $ .when.apply ($, newarray)}), затем (callback); обратный вызов не вызван ... –

+0

@YuWu - ваш синтаксис для того, что вы опубликовали в своем комментарии, неверен. В нем есть дополнительный '})'. – jfriend00

1

$.when() не создает еще один массив deferreds. Он возвращает одно обещание, которое будет разрешено, когда все обещания, которые вы передали, были разрешены (или отклонены, если какое-либо из этих обещаний отклонено).

Результаты, переданные разрешенному обработчику единого обещания, представляют собой массив результатов. В некоторых случаях (например, с $.ajax(), это будет массив массивов результатов).

Итак, что у вас было:

$.when.apply($, array).then(function(arrayOfResults) { 
    (do something here ...) 
}); 

будет прекрасно работать говорю вам, когда все обещания, вы прошли в $.when() уже finised. Код в обработчике .then() будет передан массив результатов и будет вызываться только тогда, когда все обещания, которые вы передали $.when(), были разрешены.

Если внутри обработчика .then() вы хотите запустить N более асинхронных операций, вы можете просто использовать $.when() снова внутри. Или, каждый из ваших первоначальных асинхронных вызовов хочет иметь свою собственную цепочку, тогда вы должны связать их, прежде чем передавать их на $.when(), поэтому то, что передается $.when(), является результатом цепочки каждой отдельной цепочки.

Например, вы могли бы сделать это:

var p1 = $.ajax(...).then(...).then(...).then(...).then(...); 
var p2 = $.ajax(...).then(...).then(...).then(...); 

$.when(p1, p2).then(function(arrayOfResults) { 
    // will be executed when all the chained operations in p1 and p2 are done 
}); 

Или вы могли бы сделать это для другой серии параллельных операций:

$.when.apply($, array).then(function(arrayOfResults) { 
    // first up N more async operations 
    return $.when.apply($, newArray).then(...); 
}); 

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


Основываясь на отредактированном вопрос, вы можете сделать это:

$.when.apply($, arrayOfDeferreds).then(function() { 
    var args = Array.prototype.slice.call(arguments); 

    var anotherArrayOfDeferreds = args.map(function(item){ 
     return item.getSomething(); // item.getSomething() returns an deferred. 
    }); 
    $.when.apply($, anotherArrayOfDeferreds).then(function() { 
     // called when this new array of deferreds is done 
    }); 

}); 

Но это немного необычной структурой. Обычно, если после операции async выполняется больше операций async, вы не разрешаете и не передаете элемент, который затем можно использовать для последующей операции async, а скорее вы просто связываете операцию async прямо там, где у вас есть Это.

Таким образом, вместо того, чтобы делать это в вашей первоначальной асинхронной операции:

d.resolve(item); 

, которые вы должны использовать сейчас, вы могли бы сделать это:

return item.getSomething(); 

Это просто цепь следующего асинхр на предыдущем, а ваш оригинал $.when() будет работать для всех.

+0

Извините, я не дал понять это в описании. В (сделайте что-то здесь ...), я сгенерировал массив отсрочек, которым нужно использовать $ .when.apply для обработки. Но я попробовал метод, предложенный Аруном П. Джонни, обратный вызов в .then() не вызывался. –

+0

@YuWu - тогда вы не делаете это правильно. '$ .when()' работает для массива отложенных или обещаний. Оно работает. Если это не сработает для вас, то это потому, что вы не используете его правильно, и вам нужно будет показать нам свой фактический код, чтобы мы могли помочь вам понять, что вы делаете неправильно. Теоретическое обсуждение сделано. Теперь нам нужно увидеть, что ваш фактический код, который вы говорите, не работает. – jfriend00

+0

@ jfriend00 Возможно, OP пытается описать массив фактических отложенных объектов, возвращаемых в следующий '.then()'? – guest271314

0

Во-первых, давайте назовем их обещаниями не отсроченными, потому что нет необходимости когда-либо делать подобные вещи с отсрочками.

Теперь, если вы не нуждаетесь в обещании, возвращенном $.when.apply(arrayOfPromises) для любых других целей, тогда не нужен двойной $.when().

Вы можете сопоставить arrayOfPromises с другим массивом обещаний и сделать один $.when.apply() на этом массиве.

$.when.apply($, arrayOfPromises.map(function(promise) { 
    return promise.then(function(item) { 
     return item.getSomething(); 
    }); 
})).then(function() { 
    var resultsOfTheDualAsyncProcesses = Array.prototype.slice.call(arguments); 
}); 

DEMO