6

$.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

4

3 回答 3

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,但我不确定它是否在内部使用。

于 2012-08-21T08:39:37.087 回答
1

jQuery 有一个搞乱参数逻辑的坏习惯。在您的情况下,如果您想要为每个延迟对象进行回调,一个简单的循环会对其进行规范化:

$.each(dfds, function() {
    $.when(this).done(function() {
        console.log(arguments);
    });
});

您还可以循环参数,这样您就不必发送数组:

function foo() {
    $.each(arguments, function() {
        $.when(this).done(function() {
            console.log(arguments);
        });
    });
}

更新

如果您总是想返回一个延迟对象数组,您可能需要检查fooFelix 发布的参数长度,或者执行以下操作:

function foo() {
    $.when.apply(this, arguments).done(function() {
        var args = $.makeArray(arguments),
            result = args[0].constructor != Array ? [args] : args;
        console.log(result);
    });
}

http://jsfiddle.net/2ht8d/

于 2012-08-21T08:01:22.660 回答
0

只需将虚拟对象推到 dfds 数组的末尾即可。假设您至少有一个延迟,这将确保它的长度始终为 2 或更大。

于 2012-08-21T16:32:18.363 回答