Как вы работаете с массивом jQuery Deferreds?
У меня есть приложение, которое требует загрузки данных в определенном порядке: корневой URL-адрес, затем схемы, а затем, наконец, инициализировать приложение со схемами и URL-адресами для различных объектов данных. По мере перемещения пользователя по приложению объекты данных загружаются, проверяются по схеме и отображаются. По мере того как пользователь обрабатывает данные, схемы обеспечивают проверку первого прохода.
У меня возникли проблемы с инициализацией. Я использую вызов Ajax для извлечения корневого объекта, $.when (), а затем создать массив обещаний, по одному для каждого объекта схемы. Эта работа. Я вижу выборку в консоли.
затем я вижу выборку для всех схем, поэтому каждый $.ajax () вызов работает. fetchschemas () действительно возвращает массив обещаний.
однако это последнее предложение when () никогда не срабатывает, и слово "DONE" никогда не появляется на консоли. Исходный код jquery-1.5, по-видимому, подразумевает, что "null" приемлем в качестве объекта для передачи в $.когда.применить(), как когда () создаст внутренний отложенный () объект для управления списком, если объект не передается.
это работало с использованием фьючерсов.js. Как следует управлять массивом jQuery Deferreds, если не так?
var fetch_schemas, fetch_root;
fetch_schemas = function(schema_urls) {
var fetch_one = function(url) {
return $.ajax({
url: url,
data: {},
contentType: "application/json; charset=utf-8",
dataType: "json"
});
};
return $.map(schema_urls, fetch_one);
};
fetch_root = function() {
return $.ajax({
url: BASE_URL,
data: {},
contentType: "application/json; charset=utf-8",
dataType: "json"
});
};
$.when(fetch_root()).then(function(data) {
var promises = fetch_schemas(data.schema_urls);
$.when.apply(null, promises).then(function(schemas) {
console.log("DONE", this, schemas);
});
});
4 ответа:
вы ищете
$.when.apply($, promises).then(function(schemas) { console.log("DONE", this, schemas); }, function(e) { console.log("My ajax failed"); });
это также будет работать (для некоторого значения работы он не будет исправлять сломанный ajax):
$.when.apply($, promises).done(function() { ... }).fail(function() { ... });`
вы хотите передать
$
вместоnull
, Так чтоthis
внутри$.when
относится кjQuery
. Это не должно иметь значения для источника, но это лучше, чем передачаnull
.высмеял все ваши $.ajax, заменив их на
$.when
образца работаеттак что это либо проблема в ваш ajax-запрос или массив, который вы передаете в fetch_schemas.
обходной путь выше (спасибо!) не решает должным образом проблему возврата объектов, предоставленных отложенным
resolve()
метод, потому что jQuery называетdone()
иfail()
обратные вызовы с индивидуальными параметрами, а не массив. Это означает, что мы должны использоватьarguments
псевдо-массив, чтобы получить все разрешенные / отклоненные объекты, возвращаемые массивом deferreds, что некрасиво:$.when.apply($, promises).then(function() { var schemas=arguments; // The array of resolved objects as a pseudo-array ... };
так как мы прошли в массиве deferreds, было бы неплохо вернуться массив результатов. Также было бы неплохо вернуть фактический массив вместо псевдо-массива, чтобы мы могли использовать такие методы, как
Array.sort()
.вот решение, вдохновленное когда.js ' s
when.all()
метод, который решает эти проблемы:// Put somewhere in your scripting environment if (jQuery.when.all===undefined) { jQuery.when.all = function(deferreds) { var deferred = new jQuery.Deferred(); $.when.apply(jQuery, deferreds).then( function() { deferred.resolve(Array.prototype.slice.call(arguments)); }, function() { deferred.fail(Array.prototype.slice.call(arguments)); }); return deferred; } }
теперь вы можете просто передать массив deferreds / promises и получить обратно массив разрешенных / отклоненных объектов в вашем обратном вызове, например:
$.when.all(promises).then(function(schemas) { console.log("DONE", this, schemas); // 'schemas' is now an array }, function(e) { console.log("My ajax failed"); });
Если вы используете ES6 версию javascript есть оператор распространения(...) который преобразует массив объектов в аргументы, разделенные запятыми.
$.when(...promises).then(function() { var schemas=arguments; };
подробнее об операторе распространения ES6https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator найти здесь
расширяется, когда с этим кодом:
var rawWhen = $.when $.when = function(promise) { if ($.isArray(promise)) { var dfd = new jQuery.Deferred() rawWhen.apply($, promise).done(function() { dfd.resolve(Array.prototype.slice.call(arguments)) }).fail(function() { dfd.reject(Array.prototype.slice.call(arguments)) }) return dfd.promise() } else { return rawWhen.apply($, arguments) } }