我正在开发一个JS包,用作大型应用程序的一部分,有时需要在一个组中进行未知数量的API调用,解析所有调用的响应该小组同时进行。
每当处理应该一起处理的多个Ajax调用(使用jQuery)时,使用$.when().done()
是有意义的,但因为我不知道提前需要多少个调用,所以我有使用.apply()
将所有放入<{em> $.when()
来电。
快速注意:我在启动Ajax调用的同一函数中生成了值,我需要将其返回给调用它的函数。因此看起来很奇怪的return [...]
部分。 FWIW:我的代码没有被破坏,最终结果完全符合我的要求,但我真的很讨厌使用我还不了解的代码......
有问题的代码如下:
var requestsMap = {
group1: ["call1"],
group2: ["call1", "call2"],
group3: ["call2", "call4", "call6"]
};
var requests = requestsMap[REQUEST_INPUT].map(function(_type) {
return ajaxCallWrapper(REQUEST_CONFIG, _type);
});
$.when.apply($, requests).done(function() {
// see comment after code block
});
function ajaxCallWrapper(_config, _type) {
var customUrl = _config[_type].url;
var extra1 = "...";
var extra2 = "...";
return [$.ajax({
url: customUrl,
method: "GET",
dataType: "json",
global: false
}), {
extra1: extra1,
extra2: extra2
}];
}
当我第一次发现$.when()
时,我确实注意到使用多个承诺时的不同响应模式(data, textStatus, jqXHR
)。结果,我想我可能需要做一些像......
var responses = requests.length === 1 ? [arguments] : arguments;
...当我在.done()
中获得响应时,我可以将每个响应作为回调参数循环。但即使只有一个Ajax调用,我仍然可以从第一个回调参数中获取数据,文本状态和XHR对象。
有人可以解释为什么会这样吗?
编辑以澄清。请参阅this JSFiddle以供参考。
最终编辑 - 尝试在我自己的答案中使用相同的代码,但是SO并不喜欢这样......
答案 0 :(得分:0)
$.when.apply
有点难看。 then()
或done()
中的每个参数都是一个数组,数据是数组中的一个元素(我忘记了顺序)
你基本上必须做类似的事情:
$.when.apply($, requests).done(function() {
[].slice.call(arguments).forEach(function(arg){
var data = arg[1] // guessing at index here, I forget
});
// or
var allData = [].map.call(arguments) ....
});
由于现代浏览器支持Promise API,我建议使用Promise.all()。所有jQuery deffered api都是在Promises成为常见之前构思出来的,因此$ .when仍然很难看
Promise.all(requests).then(function(resultsArray){
// resultsArray contains data from each request
});
示例:
const doRequest = (num) => {
let url = 'http://httpbin.org/get';
return $.getJSON(url, {id: num }).then(res => res.args)
}
const requests = [1, 2, 3, 4].map(doRequest);
Promise.all(requests).then(res => console.log(res))
.as-console-wrapper {
max-height: 100%!important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
答案 1 :(得分:0)
Omg ...严肃的facepalm时刻。我道歉,不知道我是怎么错过这个。
回到JSFiddle I created just now:
var d1 = $.ajax("/css/light.css");
var d2 = $.ajax("/css/light.css");
var d3 = $.ajax("/css/light.css");
$.when(d1, d2, d3).done(function (v1, v2, v3) {
console.log("v1:", v1);
console.log("v2:", v2);
console.log("v3:", v3);
});
var d4 = $.ajax("/css/light.css");
$.when(d4).done(function (v4a, v4b, v4c) {
console.log("v4a:", v4a);
console.log("v4b:", v4b);
console.log("v4c:", v4c);
});
var d5 = [$.ajax("/css/light.css")];
$.when.apply($, d5).done(function (v5a, v5b, v5c) {
console.log("v5a:", v5a);
console.log("v5b:", v5b);
console.log("v5c:", v5c);
});
var d6 = [$.ajax("/css/light.css"), $.ajax("/css/light.css")];
$.when.apply($, d6).done(function (v6a, v6b, v6c) {
console.log("v6a:", v6a);
console.log("v6b:", v6b);
console.log("v6c:", v6c);
});
在控制台中显示以下输出:
v1: (3) ["", "success", {…}]
v2: (3) ["", "success", {…}]
v3: (3) ["", "success", {…}]
v4a:
v4b: success
v4c: {readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
v5a: (3) ["", "success", {…}]
v5b: (3) ["", "success", {…}]
v5c: undefined
v1: (3) ["", "success", {…}]
v2: (3) ["", "success", {…}]
v3: (3) ["", "success", {…}]
v4a:
v4b: success
v4c: {readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
v5a:
v5b: success
v5c: {readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …}
v6a: (3) ["", "success", {…}]
v6b: (3) ["", "success", {…}]
v6c: undefined
出于某种原因,我认为我上面的5
示例中的代码仍然像6
示例中那样返回单个响应。但显然我错了。