我有一个应用程序需要按特定顺序加载数据:根URL,然后是模式,然后最终使用各种数据对象的模式和URL初始化应用程序。当用户导航应用程序时,将加载数据对象,根据模式进行验证并显示。当用户CRUD数据时,模式提供首次验证。
我遇到初始化问题。我使用Ajax调用来获取根对象$ .when(),然后创建一个promises数组,每个模式对象一个。这样可行。我在控制台中看到了提取。
然后我看到所有模式的获取,因此每个$ .ajax()调用都有效。 fetchschemas()确实返回了一个promises数组。
但是,最终when()子句永远不会触发,并且“DONE”字样永远不会出现在控制台上。 jquery-1.5的源代码似乎暗示“null”可以作为传递给$ .when.apply()的对象,因为when()将构建一个内部Deferred()对象来管理列表,如果没有对象是传入。
这使用Futures.js。如果不是这样的话,应该如何管理一组jQuery Deferred?
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);
});
});
答案 0 :(得分:196)
您正在寻找
$.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
和样本works
所以这是你的ajax请求中的一个问题,或者你传递给fetch_schemas的数组。
答案 1 :(得分:53)
上面的解决方法(谢谢!)没有正确解决返回提供给延迟的resolve()
方法的对象的问题,因为jQuery会调用done()
和fail()
个回调参数,而不是数组。这意味着我们必须使用arguments
伪数组来获取延迟数组返回的所有已解析/被拒绝的对象,这很难看:
$.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;
}
}
现在你可以简单地传入一个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");
});
答案 2 :(得分:18)
如果你使用的是ES6版本的javascript有一个扩展运算符(...)可以将对象数组转换为逗号分隔的参数。
$.when(...promises).then(function() {
var schemas=arguments;
};
有关ES6传播运营商https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator的更多信息,请点击此处
答案 3 :(得分:0)
扩展:
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)
}
}