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

2023-11-25

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

then()

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

完成回调解决 Deferred 问题时调用的函数或函数数组。
失败回调当 Deferred 被拒绝时调用的函数或函数数组。

pipe()

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

完成过滤器解决 Deferred 问题时调用的可选函数。
失败过滤器当 Deferred 被拒绝时调用的可选函数。

I know then()存在的时间比pipe()所以后者肯定会增加一些额外的好处,但我不明白到底有什么区别。两者都采用几乎相同的回调参数,尽管它们的名称不同以及返回一个Deferred并返回一个Promise看起来很轻微。

我一遍又一遍地阅读官方文档,但总是发现它们太“密集”,无法真正理解我的头脑,搜索发现了对一个功能或另一个功能的大量讨论,但我还没有找到任何真正澄清不同功能的东西各自的优点和缺点。

那么什么时候使用比较好then什么时候使用比较好pipe?


Addition

菲利克斯的出色回答确实有助于阐明这两个功能的不同之处。但我想知道是否有时then()优于pipe().

显然,pipe()then()似乎前者可以做任何后者可以做的事情。使用理由之一then()可能是它的名称反映了它作为处理相同数据的函数链的终止的角色。

但是否有一个用例需要then()正在返回原来的Deferred这是做不到的pipe()由于它返回一个新的Promise?


Since jQuery 1.8 .then行为相同.pipe:

弃用通知:从 jQuery 1.8 开始,deferred.pipe()方法已弃用。这deferred.then()应该使用替代它的方法。

and

从 jQuery 1.8 开始, the deferred.then()方法返回一个新的 Promise,可以通过函数过滤 deferred 的状态和值,替换现在已弃用的 Promisedeferred.pipe() method.

下面的示例可能对某些人仍然有帮助。


它们有不同的用途:

  • .then()每当您想要处理过程的结果时,即如文档所述,当延迟对象被解决或拒绝时,就可以使用。与使用相同.done() or .fail().

  • 你会用.pipe()到(前)filter结果不知何故。回调的返回值.pipe()将作为参数传递给done and fail回调。它还可以返回另一个延迟对象,并且以下回调将在此延迟对象上注册。

    情况并非如此.then() (or .done(), .fail()),注册回调的返回值将被忽略。

所以这不是你使用的either .then() or .pipe(). You could use .pipe()出于相同的目的.then()但反之则不成立。


实施例1

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

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

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

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() for:

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 调用。一种方法是在 a 中进行第二次调用done打回来:

$.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
        });
    });
}

您想使用延迟对象来允许其他代码调用makeCalls附加回调secondAjax 调用,但是

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

由于第二次调用是在 a 内进行的,因此不会达到预期的效果done回调并且无法从外部访问。

解决方案是使用.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 调用,而无需公开调用的实际流程/顺序。


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐