Как вы работаете с массивом jQuery Deferreds?

У меня есть приложение, которое требует, чтобы данные загружались в определенном порядке: корневой URL, затем схемы, а затем, наконец, инициализировали приложение с помощью схем и URL-адресов для различных объектов данных. Когда пользователь перемещает приложение, объекты данных загружаются, проверяются по схеме и отображаются. Поскольку пользователь CRUD передает данные, схемы обеспечивают проверку первого шага.

У меня проблема с инициализацией. Я использую вызов Ajax для извлечения корневого объекта $ .when (), а затем создаю массив обещаний, по одному для каждого объекта схемы. Это работает. Я вижу выборку в консоли.

Затем я вижу выборку для всех схем, поэтому каждый вызов $ .ajax () работает. fetchschemas () действительно возвращает массив обещаний.

Однако этот финал, когда условие () никогда не срабатывает, и слово «DONE» никогда не появляется на консоли. Исходный код для jquery-1.5, по-видимому, подразумевает, что «null» является приемлемым как объект для передачи в $ .when.apply (), как если () будет строить внутренний объект Deferred () для управления списком, если ни один объект не является прошел.

Это работало с использованием Futures.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); }); }); 

Ты ищешь

 $.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.

Обходной путь выше (спасибо!) Неправильно решает проблему возврата объектов, предоставленных в метод decfered resolve() потому что jQuery вызывает обратные вызовы done() и fail() с отдельными параметрами, а не с массивом. Это означает, что мы должны использовать arguments pseudo-array, чтобы получить все разрешенные / отклоненные объекты, возвращаемые массивом отложенных, что является уродливым:

 $.when.apply($, promises).then(function() { var schemas=arguments; // The array of resolved objects as a pseudo-array ... }; 

Поскольку мы прошли в массиве отложенных периодов, было бы неплохо вернуть массив результатов. Также было бы неплохо вернуть реальный массив вместо псевдо-массива, чтобы мы могли использовать такие методы, как Array.sort() .

Вот решение, основанное на методе when.js 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; } } 

Теперь вы можете просто передать массив отложенных / обещаний и вернуть массив разрешенных / отклоненных объектов в ваш обратный вызов, например:

 $.when.all(promises).then(function(schemas) { console.log("DONE", this, schemas); // 'schemas' is now an array }, function(e) { console.log("My ajax failed"); }); 

Если вы используете версию javascript для ES6 Существует оператор с расширением (…), который преобразует массив объектов в аргументы, разделенные запятыми.

 $.when(...promises).then(function() { var schemas=arguments; }; 

Подробнее о распространителе ES6 https://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) } } 
Давайте будем гением компьютера.