96 votes

Quand devrais-je utiliser la méthode "then" de jQuery deferred et quand devrais-je utiliser la méthode "pipe"?

jQuery Deferred a deux fonctions qui peuvent être utilisées pour mettre en œuvre asynchrone enchaînement de fonctions:

then()

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

doneCallbacks Une fonction, ou un tableau de fonctions, lorsque le Différé est résolu.
failCallbacks Une fonction, ou un tableau de fonctions, lorsque le Différé est rejetée.

pipe()

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

doneFilter Une fonction optionnelle qui est appelée lorsque le Différé est résolu.
failFilter Une fonction optionnelle qui est appelée lorsque le Différé est rejetée.

Je connais then() a été autour d'un peu plus de temps qu' pipe() de sorte que le dernier doit ajouter un peu plus d'avantages, mais la différence c'est justement m'échappe. Les deux prennent à peu près le même rappel des paramètres, s'ils diffèrent du nom et de la différence entre le retour d'un Deferred et de retourner un Promise semble légère.

J'ai lu les docs officielles et plus, mais toujours trouver trop "dense" pour vraiment envelopper ma tête autour de et de la recherche a trouvé beaucoup de discussion de la fonctionnalité ou l'autre, mais je n'ai pas trouvé quelque chose qui a vraiment précise les différents avantages et inconvénients de chaque.

Alors, quand est-il préférable d'utiliser then , et quand est-il préférable d'utiliser des pipe?


Plus

Felix est une excellente réponse a vraiment aidé à clarifier la façon dont ces deux fonctions diffèrent. Mais je me demande si il y a des moments où la fonctionnalité de then() est préférable à celle d' pipe().

Il est évident qu' pipe() est plus puissant que l' then() et il semble que l'ancien ne peut rien faire ce dernier peut faire. L'une des raisons pour utiliser then() peut-être que son nom reflète son rôle de la résiliation d'une chaîne de fonctions de traitement de données.

Mais est-il un cas d'utilisation qui exige then()s'retourner l'original Deferred qui ne peut être fait avec pipe() en raison d'une rechute d'un nouveau Promise?

103voto

Felix Kling Points 247451

Depuis jQuery 1.8 .then a le même comportement que .pipe:

La dépréciation de l'Avis: Que de jQuery 1.8, l' deferred.pipe() méthode est obsolète. L' deferred.then() méthode, qui le remplace, doit être utilisé à la place.

et

Comme de jQuery 1.8, l' deferred.then() méthode retourne une nouvelle promesse qui permet de filtrer le statut et les valeurs reportées au travers d'une fonction, en remplacement de la désormais obsolète deferred.pipe() méthode.

Les exemples ci-dessous peuvent encore être utile à certains.


Ils servent à des fins différentes:

  • .then() doit être utilisé chaque fois que vous voulez travailler avec le résultat de ce processus, à savoir que la documentation dit, lorsque le report de l'objet est résolu ou rejeté. C'est le même que l'utilisation de .done() ou .fail().

  • Vous pouvez utiliser .pipe() de (pré)filtre le résultat d'une certaine manière. La valeur de retour d'un rappel à l' .pipe() sera passé en argument de la done et fail rappels. Il peut aussi retourner une autre différée objet et les rappels suivants seront enregistrés sur cette différé.

    Ce n'est pas le cas avec .then() (ou .done(), .fail()), les valeurs de retour des rappels enregistrés sont tout simplement ignorées.

Donc, ce n'est pas que vous utilisez soit .then() ou .pipe(). Vous pourriez utiliser .pipe() pour les mêmes fins que l' .then() , mais l'inverse ne tient pas.


Exemple 1

Le résultat d'une opération est un ensemble d'objets:

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

et vous voulez calculer le minimum et le maximum des valeurs. Supposons que nous utilisons deux done rappels:

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" */ 

});

Dans les deux cas, vous devez parcourir la liste et d'en extraire la valeur de chaque objet.

Ne serait-il pas mieux de faire en quelque sorte extraire les valeurs d'avance de sorte que vous n'avez pas à le faire dans les deux rappels individuellement? Oui! Et c'est ce que l'on peut utiliser .pipe() pour:

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" */

});

Bien évidemment, ceci est un exemple, et il ya de nombreux différents (peut-être mieux) des moyens pour résoudre ce problème, mais j'espère que ça illustre bien le propos.


Exemple 2

Examiner les appels Ajax. Parfois, vous voulez lancer un appel Ajax après une précédente est terminée. Une façon est de faire l'appel de la deuxième à l'intérieur d'un done de rappel:

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

Maintenant, supposons que vous souhaitez dissocier votre code et de mettre ces deux appels Ajax à l'intérieur d'une fonction:

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

Vous souhaitez utiliser le différée objet de permettre à d'autres de code qui appelle makeCalls d'attacher des rappels pour le deuxième appel Ajax, mais

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

n'aurait pas l'effet désiré que le deuxième appel est effectué à l'intérieur d'un done de rappel et ne sont pas accessibles de l'extérieur.

La solution serait d'utiliser des .pipe() à la place:

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

En utilisant .pipe() vous pouvez maintenant possible d'ajouter des rappels à l' "intérieure" appel Ajax sans exposer le débit réel/ordre des appels.


En général, les différés d'objets fournir un moyen intéressant de dissocier votre code :)

7voto

Alex Feinman Points 2678

Il n'y a aucun cas où vous DEVEZ utiliser then() sur pipe(). Vous pouvez toujours choisir d'ignorer la valeur pipe() passe. Il y a peut - être un léger gain de performance pour l'utilisation de pipe - mais il est peu probable que la matière.

Donc, il pourrait sembler que vous pouvez simplement utiliser toujours pipe() dans les deux cas. Cependant, en utilisant pipe(), vous communiquez à d'autres personnes de la lecture de votre code (y compris vous-même, de six mois à partir de maintenant) qu'il existe une certaine importance à la valeur de retour. Si vous êtes à la jeter, vous êtes en violation de cette sémantique de construire.

C'est comme avoir une fonction qui retourne une valeur qui n'est jamais utilisé: confusion.

Donc, utiliser l' then() lorsque vous devez, et pipe() lorsque vous devez...

5voto

hippietrail Points 4257

En fait il s'avère que la différence entre .then() et .pipe() a été jugé inutile, et ils ont été faits pour être la même que celle de la version jQuery 1.8.

À partir d' un commentaire en jaubourg jQuery dans le bug tracker ticket #11010 "FAIRE DIFFÉRÉ.ALORS == DIFFÉRÉS.PIPE COMME LA PROMESSE/A":

En 1.8, nous allons supprimer l'ancienne et la remplacer par des tuyaux actuel. Mais la très sadening conséquence est que nous allons avoir à dire aux gens d'utiliser la non-standard de fait, l'échec et de progrès, parce que la proposition ne fournit pas simple, EFFICACE, il suffit d'ajouter un rappel.

(emphassis le mien)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X