什么时候应该使用jQuery推迟的"然后"法当我应该使用"管"方法? [英] When should I use jQuery deferred's "then" method and when should I use the "pipe" method?

查看:182
本文介绍了什么时候应该使用jQuery推迟的"然后"法当我应该使用"管"方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

jQuery的 递延 有两个功能,这可以被用来实现的功能异步链接:

则()


  

deferred.then(doneCallbacks,failCallbacks)返回:延迟


  
  

doneCallbacks :一种功能或功能阵列,当递延得到解决调用。结果
   failCallbacks :一种功能或功能阵列,当递延称为被拒绝。


管道()


  

deferred.pipe([doneFilter] [,failFilter])返回:无极


  
  

doneFilter 的可选功能,当递延得到解决时调用。结果
   failFilter 可选功能时,延期被拒绝被调用。


我知道则()已经有一点点的时间比管道()所以后者必须添加一些额外的好处,但又有什么区别precisely就是我摸不透。无论采取pretty几乎相同的回调参数,虽然他们的名字不同,返回之间的差异递延并返回无极似乎轻微的。

我一遍又一遍地阅读官方文档,但总是发现他们太密真正绕到我的头和搜索发现很多的一个特征或其他的讨论,但我没有发现任何东西真的明确每个不同的利弊。

所以,当是它更好地使用然后时是它更好地使用管道 <? / STRONG>


添加

Felix的出色答卷真正有助于澄清这两个函数的不同之处。但我不知道是否有时间时的功能则()是preferable到管道()

显然,管道()更强大比则(),似乎前者可以做任何后者可以做到的。原因之一使用则()可能是因为它的名字反映其作为功能处理相同的数据链的终止作用。

但是有一个需要则()的返回原始递延,一个用例不能用完成管道(),由于它返回一个新的无极


解决方案

由于的jQuery 1.8 。然后的行为一样 .pipe


  

德precation注意:在jQuery 1.8中, deferred.pipe()方法是pcated德$ P $。在 deferred.then()方法,该方法取代它,应该使用。



  

在jQuery 1.8 deferred.then()方法返回一个新的承诺,可以过滤通过延迟的状态和值功能,取代pcated现在德$ p $ deferred.pipe()方法。


下面的例子可能仍然会有所帮助一些。


他们为不同的目的:


  • 。然后()是,每当你想与过程的结果工作,即作为文件说,当递延对象是使用解决或拒绝。这是与使用 .done() .fail()


  • 您会使用 .pipe()来(pre)的过滤器的结果不知何故。回调的返回值 .pipe()将作为参数传递给完成和<$ C $传递C>失败回调。它也可以返回另一个递延对象,下面回调将在此延期注册。

    这是不是与。然后()(或 .done(),<$ C $的情况下C> .fail()),已注册的回调的返回值将被忽略。


因此​​,这不是你使用的或者。然后()。管()。您的可能的使用 .pipe()用于同样用途的。然后(),但反之不成立。


例1

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

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

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

  deferred.then(功能(结果){
    //结果= [{值:2},{值:4},{值:6}]    变种值= [];
    对于(VAR I = 0,LEN = result.length; I&LT; LEN,我++){
        values​​.push(结果[I]。价值);
    }
    变种分钟= Math.min.apply(数学,数值);   / *做一些与分* /}),然后(功能(结果){
    //结果= [{值:2},{值:4},{值:6}]    变种值= [];
    对于(VAR I = 0,LEN = result.length; I&LT; LEN,我++){
        values​​.push(结果[I]。价值);
    }
    VAR最大= Math.max.apply(数学,数值);   / *做一些与最大* /});

在你必须遍历列表和提取每个对象的值这两种情况。

那岂不是更好地以某种方式预先提取值,这样你就不必做这两个单独的回调?是!这就是我们可以用什么 .pipe()为:

  deferred.pipe(功能(结果){
    //结果= [{值:2},{值:4},{值:6}]    变种值= [];
    对于(VAR I = 0,LEN = result.length; I&LT; LEN,我++){
        values​​.push(结果[I]。价值);
    }
    返回值; // [2,4,6]}),然后(功能(结果){
    //结果= [2,4,6]    变种分钟= Math.min.apply(数学,结果);    / *做一些与分* /}),然后(功能(结果){
    //结果= [2,4,6]    VAR最大= Math.max.apply(数学,结果);    / *做一些与最大* /});

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


例2

考虑Ajax调用。有时你想发起一个previous一个操作完成后的一个Ajax调用。一种方法是让完成回调内部的第二个电话:

  $。阿贾克斯(...)。完成(功能(){
    //首先阿贾克斯后执行
    $阿贾克斯(...)。完成(功能(){
        //第二个电话后执行
    });
});

现在让我们假设你想解耦code和把这两个阿贾克斯在函数内部调用:

 函数makeCalls(){
    //这里我们返回`$阿贾克斯()的返回值。()完成`,它
    //是由`$。阿贾克斯()`独自回到同一递延对象    返回$阿贾克斯(...)。完成(功能(){
        //第一个电话后执行
        $阿贾克斯(...)。完成(功能(){
            //第二个电话后执行
        });
    });
}

您想使用递延对象允许其他code这就要求 makeCalls 附加回调的的第二的Ajax调用但

  makeCalls()。完成(功能(){
    //这是第一个Ajax调用后执行
});

不会收到预期的效果作为第二个电话是完成回调中所做的,而不是从外部访问。

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

 函数makeCalls(){
    //这里我们返回`$阿贾克斯()的返回值。管()',这是
    //新的递延/承诺对象,并连接到返回的
    //通过传递给`pipe`回调    返回$阿贾克斯(...)。管(函数(){
        //第一个电话后执行
        返回$阿贾克斯(...)。完成(功能(){
            //第二个电话后执行
        });
    });
}makeCalls()。完成(功能(){
    //这是第二个Ajax调用后执行
});

通过使用 .pipe()你现在可以使人们有可能追加回调内部Ajax调用不暴露呼叫的实际流量/订单。


在一般情况下,延迟对象提供一种有趣的方式来解耦code:)

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

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.

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 Deferred and returning a Promise seems slight.

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 then and when is it better to use pipe?


Addition

Felix's excellent answer has 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().

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.

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

解决方案

Since jQuery 1.8 .then behaves the same as .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.

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.

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)filter the result somehow. The return value of a callback to .pipe() will be passed as argument to the done and fail callbacks. 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.

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


Example 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 done callbacks:

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:

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

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 done callback:

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

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 makeCalls to attach callbacks for the second Ajax call, but

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 done callback and not accessible from the outside.

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

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.


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

这篇关于什么时候应该使用jQuery推迟的&QUOT;然后&QUOT;法当我应该使用&QUOT;管&QUOT;方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆