$。当行为不同时,取决于是否将一个或多个Deferred对象传递给它。这种行为记录在文档中 - 但问题是它迫使我编写两个不同的代码路径。
function foo (dfds) {
$.when.apply(this, dfds).done(function() {
console.log(arguments);
});
}
案例I:
foo([$.getJSON("http://freegeoip.net/json/8.8.8.8"),
$.getJSON("http://freegeoip.net/json/8.8.8.9")]);
....
/* Output (what I'd come to expect) */
[Array[3], Array[3]]
案例II:
foo([$.getJSON("http://freegeoip.net/json/8.8.8.8")]);
....
/* Output (the original unwrapped deferred's arguments) */
[Object, "success", Object]
如何优雅地处理此问题而无需检查dfd
的长度或arguments
的类型?
答案 0 :(得分:4)
我认为你不能避免显式测试延迟对象的数量。假设您要返回延迟对象:
function foo (dfds) {
if(dfds.length > 1) {
return $.when.apply(this, dfds);
}
else {
return dfds[0].pipe(function() {
return [Array.prototype.slice.call(arguments, 0)]
});
}
}
您可以创建一个jQuery插件来包装此功能并使其可重用:
(function($) {
$.when_ = function() {
if(arguments.length > 1) {
return $.when.apply(this, arguments);
}
else {
return arguments[0].pipe(function() {
return [Array.prototype.slice.call(arguments, 0)];
});
}
};
}(jQuery));
你也可以覆盖$.when
,但我不确定它是否在内部使用。
答案 1 :(得分:1)
jQuery有一个乱搞参数逻辑的坏习惯。在您的情况下,如果您想要为每个延迟对象进行回调,则一个简单的循环会对其进行规范化:
$.each(dfds, function() {
$.when(this).done(function() {
console.log(arguments);
});
});
您也可以循环参数,这样您就不必发送数组:
function foo() {
$.each(arguments, function() {
$.when(this).done(function() {
console.log(arguments);
});
});
}
<强>更新强>
如果你总是想要返回一个延迟对象的数组,你可能需要像Felix发布的那样检查foo
中的参数长度,或者执行以下操作:
function foo() {
$.when.apply(this, arguments).done(function() {
var args = $.makeArray(arguments),
result = args[0].constructor != Array ? [args] : args;
console.log(result);
});
}
答案 2 :(得分:0)
只需将虚拟对象推到dfds数组的末尾即可。这将确保它始终具有2或更大的长度,假设您至少有一个延迟。