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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9583783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 11:00:29  来源:igfitidea点击:

When should I use jQuery deferred's "then" method and when should I use the "pipe" method?

jqueryasynchronousjquery-deferreddecouplingjquery-chaining

提问by hippietrail

jQuery's Deferredhas two functions which can be used to implement asynchronous chaining of functions:

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

then()

then()

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

doneCallbacksA function, or array of functions, called when the Deferred is resolved.
failCallbacksA function, or array of functions, called when the Deferred is rejected.

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

doneCallbacks在解析 Deferred 时调用的函数或函数数组。
failCallbacks一个函数或函数数组,在 Deferred 被拒绝时调用。

pipe()

pipe()

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

doneFilterAn optional function that is called when the Deferred is resolved.
failFilterAn optional function that is called when the Deferred is rejected.

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

doneFilter一个可选函数,在解析 Deferred 时调用。
failFilter当延迟被拒绝时调用的可选函数。

I know then()has been around a little longer than pipe()so the latter must add some extra benefit, but what the difference precisely is eludes me. Both take pretty much the same callback parameters though they differ in name and the difference between returning a Deferredand returning a Promiseseems slight.

我知道then()已经存在了一段时间,pipe()所以后者必须增加一些额外的好处,但我不知道究竟有什么区别。尽管名称不同,但两者都采用几乎相同的回调参数,并且返回 aDeferred和返回 a之间的区别Promise似乎很小。

I've read the official docs over and over but always find them too "dense" to really wrap my head around and searching has found lots of discussion of the one feature or the other but I haven't found anything that really clarifies the different pros and cons of each.

我一遍又一遍地阅读官方文档,但总是发现它们太“密集”而无法真正将我的头包围,并且搜索发现了很多关于一个功能或另一个功能的讨论,但我没有找到任何真正阐明不同之处的内容各有利弊。

So when is it better to use thenand when is it better to use pipe?

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



Addition

添加

Felix's excellent answerhas really helped clarify how these two functions differ. But I wonder if there are times when the functionality of then()is preferable to that of pipe().

Felix 的出色回答确实有助于阐明这两个函数的不同之处。但我不知道是否有时间时的功能then()是最好的那个pipe()

It is apparent that pipe()is more powerful than then()and it seems the former can do anything the latter can do. One reason to use then()might be that its name reflects its role as the termination of a chain of functions processing the same data.

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

But is there a use case that requires then()'s returning the original Deferredthat can't be done with pipe()due to it returning a new Promise?

但是是否有一个用例需要then()返回由于返回新的而Deferred无法完成的原件?pipe()Promise

回答by Felix Kling

Since jQuery 1.8.thenbehaves the same as .pipe:

由于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.

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

and

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.

从 jQuery 1.8 开始,该deferred.then()方法返回一个新的 promise,它可以通过函数过滤延迟的状态和值,替换现在已弃用的deferred.pipe()方法。

The examples below might still be helpful to some.

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



They serve different purposes:

它们有不同的用途:

  • .then()is to be used whenever you want to work with the result of the process, i.e. as the documentation says, when the deferred object is resolved or rejected. It is the same as using .done()or .fail().

  • You'd use .pipe()to (pre)filterthe result somehow. The return value of a callback to .pipe()will be passed as argument to the doneand failcallbacks. It can also return another deferred object and the following callbacks will be registered on this deferred.

    That is not the case with .then()(or .done(), .fail()), the return values of the registered callbacks are just ignored.

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

  • 您习惯于.pipe()以某种方式(预)过滤结果。回调的返回值.pipe()将作为参数传递给donefail回调。它还可以返回另一个延迟对象,并且将在此延迟上注册以下回调。

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

So it is not that you use either.then()or.pipe(). You coulduse .pipe()for the same purposes as .then()but the converse does not hold.

因此,这不是你使用两种.then().pipe()。您可以将其.pipe()用于相同的目的,.then()但反过来不成立。



Example 1

示例 1

The result of some operation is an array of objects:

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

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

and you want to compute the minimum and maximum of the values. Lets assume we use two donecallbacks:

并且您想计算这些值的最小值和最大值。假设我们使用两个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" */ 

});

In both cases you have to iterate over the list and extract the value from each object.

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

Wouldn't it be better to somehow extract the values beforehand so that you don't have to do this in both callbacks individually? Yes! And that's what we can use .pipe()for:

事先以某种方式提取值以便您不必在两个回调中单独执行此操作不是更好吗?是的!这就是我们可以使用.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" */

});

Obviously this is a made up example and there are many different (maybe better) ways to solve this problem, but I hope it illustrates the point.

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



Example 2

示例 2

Consider Ajax calls. Sometimes you want to initiate one Ajax call after a previous one completes. One way is to make the second call inside a donecallback:

考虑 Ajax 调用。有时您想在前一个调用完成后启动一个 Ajax 调用。一种方法是在done回调中进行第二次调用:

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

Now lets assume you want to decouple your code and put these two Ajax calls inside a function:

现在让我们假设您想解耦代码并将这两个 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
        });
    });
}

You'd like to use the deferred object to allow other code which calls makeCallsto attach callbacks for the secondAjax call, but

您想使用延迟对象来允许其他代码调用makeCalls附加回调以用于第二个Ajax 调用,但是

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

would not have the desired effect as the second call is made inside a donecallback and not accessible from the outside.

不会产生预期的效果,因为第二次调用是在done回调内部进行的,并且无法从外部访问。

The solution would be to use .pipe()instead:

解决方案是.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
});

By using .pipe()you can now make it possible to append callbacks to the "inner" Ajax call without exposing the actual flow/order of the calls.

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



In general, deferred objects provide an interesting way to decouple your code :)

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

回答by Alex Feinman

There is no case where you MUST use then()over pipe(). You can always choose to ignore the value that pipe()will pass in. There mightbe a slight performance hit for using pipe-- but it is unlikely to matter.

在任何情况下都必须使用then()over pipe()。您始终可以选择忽略pipe()将传入的值。使用可能会对性能造成轻微影响pipe——但这不太重要。

So it might seem like you could simply always use pipe()in both cases. However, by using pipe(), you are communicating to other people reading your code (including yourself, six months from now) that there is some importanceto the return value. If you're discarding it, you're violating this semantic construct.

因此,您似乎可以pipe()在这两种情况下始终使用。但是,通过使用pipe(),您正在向阅读您代码的其他人(包括您自己,六个月后)传达返回值的重要性。如果你丢弃它,你就违反了这个语义结构。

It's like having a function that returns a value that is never used: confusing.

这就像有一个函数返回一个从未使用过的值:令人困惑。

So use then()when you should, and pipe()when you should...

所以then()应该pipe()在什么时候使用,什么时候应该......

回答by hippietrail

In fact it turns out that the difference between .then()and .pipe()has been deemed unnecessary and they have been made to be the same as of jQuery version 1.8.

事实上,事实证明.then()和之间的区别.pipe()被认为是不必要的,并且它们已经与 jQuery 1.8 版相同。

From a comment by jaubourgin jQuery's bug tracker ticket #11010"MAKE DEFERRED.THEN == DEFERRED.PIPE LIKE PROMISE/A":

有注释jaubourg的jQuery的bug跟踪票#11010“MAKE DEFERRED.THEN == DEFERRED.PIPE LIKE PROMISE / A”:

In 1.8, we will remove the old then and replace it with current pipe.But the very sadening consequence is that we'll have to tell people to use the non-standard done, fail and progress, because the proposal doesn't provide simple, EFFICIENT, mean to just add a callback.

在 1.8 中,我们将删除旧的 then 并用当前管道替换它。但非常可悲的后果是,我们将不得不告诉人们使用非标准的 done、fail 和 progress,因为该提案没有提供简单、高效的方法,意味着只添加回调。

(emphassis mine)

(强调我的)