Javascript 更好的方法来处理JQuery$中数量可变的延迟请求。何时调用?
我正在编写一个应用程序,在某一点上需要在继续之前获得一些请求的结果。这似乎是在时使用JQuery的Javascript 更好的方法来处理JQuery$中数量可变的延迟请求。何时调用?,javascript,jquery,json,jquery-deferred,.when,Javascript,Jquery,Json,Jquery Deferred,.when,我正在编写一个应用程序,在某一点上需要在继续之前获得一些请求的结果。这似乎是在时使用JQuery的的一个可能的候选。例如: // requests is an array of Deferreds $.when.apply(null, requests).done(function(results) { // process results } 问题在于请求的数量可以是1,也可以更多,而when函数处理这些情况的方式不同。只有一个请求时,回调会获取标准(data、textSta
的一个可能的候选。例如:
// requests is an array of Deferreds
$.when.apply(null, requests).done(function(results) {
// process results
}
问题在于请求的数量可以是1,也可以更多,而when
函数处理这些情况的方式不同。只有一个请求时,回调会获取标准(data、textStatus、jqXHR)参数,但是当提供多个请求时,回调会接收一系列参数:每个请求的(data、textStatus、jqXHR)值数组。令人沮丧的是,JQuery似乎将单例请求数组视为单参数请求,这意味着必须以不同的方式处理这种情况
我所能想出的最好的办法是把这些情况分开,这让我觉得有点笨拙,而且由于不同情况下的结果参数的微妙性,我花了一段时间才弄清楚,然后,请求数组的新手需要包装在一个函数中,以便在闭包中访问它
$.when.apply(null, function (){return requests;}()).done(function(results) {
if (requests.length == 1) {
processResults(results);
} else {
for (var i=0; i < arguments.length; i++)
processResults(arguments[i][0]);
}
moreStuff();
});
$.when.apply(null,函数(){return requests;}()).done(函数(结果){
if(requests.length==1){
处理结果(结果);
}否则{
for(var i=0;i
有比这更好或更优雅的方法吗?我知道这是一个老问题,但最近我遇到了这个问题,我在搜索这个问题时遇到了这个问题。我最终创建了自己的解决方案,所以我想在这里分享它作为一个答案
简言之,$.when()
的设计并不能很好地用于动态数量的参数。事实上,动态参数有点糟糕。它既难以使用,又行为不一致
ES6 promises规范的设计者似乎同意这一点,因为那里的模拟Promise.all()
设计不同,解决了这两个问题。因此,我能想到的处理jQuery的$.when()
问题的最好办法是制作一个新版本,它遵循Promise.all()
规则,因此使用起来更简单。jQuery Ajax承诺返回一个包含三个值的数组,这些值以您提到的奇怪方式与$.when()
交互,这让生活变得更加复杂
因此,对$有两个主要更改。when()
要生成$。all()
:
使其接受一系列承诺,而不是承诺的单独参数。这使您不必只使用.apply()
向$.all()
发送数量可变的承诺
使结果表单$。无论最初传递了多少个承诺,all()
始终是数组形式。这就是你在问题中提出的前后矛盾。幸运的是,修复这个问题不需要很多代码
可以这样做:
$.all = function (promises) {
if (!Array.isArray(promises)) {
throw new Error("$.all() must be passed an array of promises");
}
return $.when.apply($, promises).then(function () {
// if single argument was expanded into multiple arguments, then put it back into an array
// for consistency
if (promises.length === 1 && arguments.length > 1) {
// put arguments into an array
return [Array.prototype.slice.call(arguments, 0)];
} else {
return Array.prototype.slice.call(arguments, 0);
}
})
};
您使用它就像$.when()
一样,只是您总是传递$.all()
一个作为承诺数组的单个参数(不再需要.apply()
),并且它总是解析为一个作为结果数组的单个参数(更容易迭代承诺结果的动态数量,并且总是一致的).
因此,如果您有一个任意长度的ajax承诺数组:
var promises = [url1, url2, url3].map(function(url) {
return $.get(url);
});
$.all(promises).then(function(results) {
// results are always consistent here no matter how many promises
// were originally passed in, thus solving your original problem
for (var i = 0; i < results.length; i++) {
console.log(results[i]);
}
});
var promises=[url1,url2,url3].map(函数(url){
返回$.get(url);
});
$.all(承诺)。然后(函数(结果){
//无论有多少承诺,结果总是一致的
//是最初传入的,因此解决了您最初的问题
对于(var i=0;i
我有一个类似的情况,我有固定数量的唯一延迟请求,但根据具体情况,我不想进行所有这些调用,因此,我不想处理所有响应。我的方法是创建一个返回空响应的虚拟延迟
// this immediately returns whatever
// is passed in as response
function emptyAjaxResponse(response) {
var deferred = $.Deferred().resolve(response);
return deferred.promise();
}
function multipleAjaxCalls(someCondition) {
// promise1 always needs to happen
var promise1 = jQuery.getJSON("some url");
// promise2 is always an array, but if someCondition is
// not met, we won't bother to make the actual request,
// just feed in an empty array.
var promise2 = someCondition ? jQuery.getJSON("some other url") : emptyAjaxResponse([]);
$.when(promise1, promise2).done(response1, response2) {
// now, we can process response1 and response2
// appropriately whether we made an actual ajax
// call on promise2 or not.
}
}
当然,在发布之后,我马上想到了一个比较明显的答案,即对于n==1的情况,这里不where
。这方面有什么进展吗?为什么要将函数作为第二个参数传递给when.apply
这不是一种改进,而是一种稍微不同的方法$.when.apply($,requests).then(function(results){if(requests.length==1){return[results];}else{return$.map(results,function(args){return args[0];});}}}).done(函数(结果){$.each(结果,函数(结果){processResults(结果);});moreStuff();})
如果没有这个,请求数组在闭包中是未定义的。我想是因为数组在JavaScript中是按值传递的。我知道JavaScript中有闭包,所以我在这里很可能是错的。你能分享发出调用的out函数吗?你也看了上面的代码片段吗