我正在编写一个应用程序,在某个时候需要在继续之前获得一些请求的结果。这似乎是使用 JQuery 的 when
的可能候选者。例如:
// 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()
的设计确实不适合用于动态数量的参数。事实上,动态论证有点糟糕。它既难用又行为不一致。
似乎 ES6 promise 规范的设计者同意,因为 Promise.all()
的模拟设计不同并且解决了这两个问题。所以,我能想到的处理 jQuery 的 $.when()
问题的最好办法是制作一个遵循 Promise.all()
规则的新版本因此使用起来更简单。 jQuery Ajax promise 返回一个包含三个值的数组,这些值以您提到的奇怪方式与 $.when()
交互,这让生活变得更加复杂。
因此,$.when()
有两个主要更改以生成 $.all()
:
让它接受一组 promise ,而不是单独的 promise 参数。这使您不必使用
.apply()
只是为了向$.all()
发送可变数量的 promise 。使
$.all()
的结果始终为数组形式,无论最初传入了多少 promise。这就是您在你的问题。幸运的是,不需要很多代码就可以解决这个问题。
可以这样做:
$.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()
一个单一的参数,它是一个promises数组(不需要.apply()
)并且它总是解析为一个结果数组的单个参数(更容易迭代 promise 结果的动态数字并且它总是一致的)。
因此,如果您有一个任意长度的 ajax promise 数组:
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]);
}
});
关于javascript - 在 JQuery $.when 调用中处理可变数量的延迟请求的更好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20233478/