什么时候应该使用jQuery deferred的“then”方法,什么时候应该使用“pipe”方法?

jQuery的Deferred有两个函数可以用来实现异步链接的函数:

then()

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

doneCallbacks A function, or array of functions, called when the Deferred is resolved.
failCallbacks A function, or array of functions, called when the Deferred is rejected.

pipe()

deferred.pipe( [doneFilter] [, failFilter] ) Returns: Promise

doneFilter An optional function that is called when the Deferred is resolved.
failFilter An optional function that is called when the Deferred is rejected.

我知道,然后()已经比管()更长一点,所以后者必须增加一些额外的好处,但什么区别正是不说我。两者采用几乎相同的回调参数,尽管它们名称不同,返回Deferred和返回Promise之间的区别似乎很轻微。

我已经读过官方文档,但总是发现他们太“密”,真的包装我的头,搜索发现了很多讨论的一个功能或其他,但我没有找到任何真正澄清的不同各自的利弊。

所以,什么时候更好使用,那么什么时候更好使用管道?

加成

Felix’s excellent answer真的帮助澄清了这两个功能的区别。但我不知道是否有时,then()的功能比管()的功能更好。

很明显,pipe()比then()更强大,似乎前者可以做任何后者可以做的事情。使用then()的一个原因可能是其名称反映其作为处理相同数据的函数链的终止的角色。

但是有一个用例,需要then()返回原来的Deferred,不能用pipe()做,因为它返回一个新的Promise?

由于jQuery 1.8 .then的行为与.pipe相同:

Deprecation Notice: As of jQuery 1.8, the deferred.pipe() method is deprecated. The deferred.then() method, which replaces it, should be used instead.

As of jQuery 1.8, the deferred.then() method returns a new promise that can filter the status and values of a deferred through a function, replacing the now-deprecated deferred.pipe() method.

下面的例子可能对一些人有帮助。

它们具有不同的用途:

> .then()用于每当你想使用进程的结果,即文档说,当延迟对象被解决或拒绝时。它与使用.done()或.fail()相同。
>你会使用.pipe()来(预)过滤结果不知何故。回调到.pipe()的返回值将作为参数传递给done和fail回调。它也可以返回另一个延迟对象,并且以下回调将在此延迟上注册。

这不是.then()(或.done(),.fail())的情况,注册的回调的返回值只是被忽略。

所以它不是你使用.then()或.pipe()。您可以使用.pipe()与.then()相同的目的,但是反之不成。

实施例1

一些操作的结果是一个对象数组:

[{value: 2}, {value: 4}, {value: 6}]

并且要计算值的最小值和最大值。假设我们使用两个完成的回调:

deferred.then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var min = Math.min.apply(Math, values);

   /* do something with "min" */

}).then(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    var max = Math.max.apply(Math, values);

   /* do something with "max" */ 

});

在这两种情况下,都必须遍历列表并从每个对象中提取值。

不是更好的以某种方式事先提取的值,这样你不必在单独的两个回调中这样做?是!这就是我们可以使用.pipe():

deferred.pipe(function(result) {
    // result = [{value: 2}, {value: 4}, {value: 6}]

    var values = [];
    for(var i = 0, len = result.length; i < len; i++) {
        values.push(result[i].value);
    }
    return values; // [2, 4, 6]

}).then(function(result) {
    // result = [2, 4, 6]

    var min = Math.min.apply(Math, result);

    /* do something with "min" */

}).then(function(result) {
    // result = [2, 4, 6]

    var max = Math.max.apply(Math, result);

    /* do something with "max" */

});

显然,这是一个弥补的例子,有许多不同的(也许更好的)方法来解决这个问题,但我希望它说明了一点。

实施例2

考虑Ajax调用。有时,您希望在上一个完成后发起一个Ajax调用。一种方法是使第二个调用在完成回调中:

$.ajax(...).done(function() {
    // executed after first Ajax
    $.ajax(...).done(function() {
        // executed after second call
    });
});

现在让我们假设你想解耦你的代码,并把这两个Ajax调用内的函数:

function makeCalls() {
    // here we return the return value of `$.ajax().done()`, which
    // is the same deferred object as returned by `$.ajax()` alone

    return $.ajax(...).done(function() {
        // executed after first call
        $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

您希望使用deferred对象允许其他调用makeCalls的代码为第二个Ajax调用附加回调,但是

makeCalls().done(function() {
    // this is executed after the first Ajax call
});

将不具有期望的效果,因为第二调用在完成的回调内部进行并且不能从外部访问。

解决方案是使用.pipe():

function makeCalls() {
    // here we return the return value of `$.ajax().pipe()`, which is
    // a new deferred/promise object and connected to the one returned
    // by the callback passed to `pipe`

    return $.ajax(...).pipe(function() {
        // executed after first call
        return $.ajax(...).done(function() {
            // executed after second call
        });
    });
}

makeCalls().done(function() {
    // this is executed after the second Ajax call
});

通过使用.pipe(),您现在可以将回调附加到“内部”Ajax调用,而不显示调用的实际流/顺序。

一般来说,延迟对象提供了一种有趣的方法来解耦你的代码:)

http://stackoverflow.com/questions/9583783/when-should-i-use-jquery-deferreds-then-method-and-when-should-i-use-the-pip

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:什么时候应该使用jQuery deferred的“then”方法,什么时候应该使用“pipe”方法?