Как вы работаете с массивом jQuery Deferreds?
У меня есть приложение, которое требует загрузки данных в определенном порядке: корневой URL, затем схемы, а затем, наконец, инициализировать приложение со схемами и URL-адресами для различных объектов данных. Когда пользователь перемещается по приложению, объекты данных загружаются, проверяются по схеме и отображаются. Когда пользователь CRUD обрабатывает данные, схемы обеспечивают проверку первого прохода.
У меня проблема с инициализацией. Я использую Ajax-вызов для извлечения корневого объекта $.when(), а затем создаю массив обещаний, по одному для каждого объекта схемы. Это работает. Я вижу выборку в консоли.
Затем я вижу выборку для всех схем, поэтому каждый вызов $.ajax() работает. fetchschemas() действительно возвращает массив обещаний.
Однако это заключительное предложение when () никогда не срабатывает, и слово "DONE" никогда не появляется на консоли. Исходный код jquery-1.5, по-видимому, подразумевает, что "null" является приемлемым в качестве объекта для передачи в $.when.apply(), так как when () создаст внутренний объект 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);
});
});
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
...
};
Поскольку мы передали массив отсрочек, было бы неплохо вернуть массив результатов. Также было бы неплохо получить реальный массив вместо псевдомассива, чтобы мы могли использовать такие методы, как Array.sort()
,
Вот решение, вдохновленное когда .jswhen.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)
}
}