Jquery:$ .when根据参数的数量表现不同
$ .when的行为会有所不同,具体取决于是否将一个或多个Deferred对象传递给它。 这种行为记录在文档中 – 但问题是它迫使我编写两个不同的代码路径。
function foo (dfds) { $.when.apply(this, dfds).done(function() { console.log(arguments); }); }
案例一:
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]]
案例二:
foo([$.getJSON("http://freegeoip.net/json/8.8.8.8")]); .... /* Output (the original unwrapped deferred's arguments) */ [Object, "success", Object]
有没有办法优雅地处理这个而不需要检查dfd
的长度或arguments
的类型?
我认为你不能避免显式测试延迟对象的数量。 假设您要返回延迟对象:
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并使其可重用:
(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
但我不确定它是否在内部使用。
jQuery有一个乱搞参数逻辑的坏习惯。 在您的情况下,如果您想要为每个延迟对象进行回调,则一个简单的循环会对其进行规范化:
$.each(dfds, function() { $.when(this).done(function() { console.log(arguments); }); });
您还可以循环参数,这样您就不必发送数组:
function foo() { $.each(arguments, function() { $.when(this).done(function() { console.log(arguments); }); }); }
UPDATE
如果你总是希望返回一个延迟对象数组,你可能需要像Felix发布的那样检查foo
的参数长度,或者执行以下操作:
function foo() { $.when.apply(this, arguments).done(function() { var args = $.makeArray(arguments), result = args[0].constructor != Array ? [args] : args; console.log(result); }); }
只需将虚拟对象推到dfds数组的末尾即可。 这将确保它始终具有2或更大的长度,假设您至少有一个延迟。