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 un enchaînement asynchrone des fonctions:

then()

deferred.then( doneCallbacks, failCallbacks ) Returns: Deferred

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

failCallbacks fonction, ou ensemble de fonctions, appelée lorsque le différé est rejeté.

pipe()

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

doneFilter une fonction optionnelle qui est appelée lorsque le différé est résolu.

failFilter An fonction optionnelle appelée lorsque le différé est rejeté.

je sais then() a été autour d'un peu plus de 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 les mêmes paramètres de rappel bien qu'ils diffèrent dans le nom et la différence entre retourner un Deferred et retourner un Promise semble légère.

j'ai lu l'officiel docs encore et encore, mais toujours les trouver trop "dense" pour vraiment envelopper ma tête autour et la recherche a trouvé beaucoup de discussion de l'un ou l'autre trait, mais je n'ai rien trouvé qui clarifie vraiment les différents avantages et inconvénients de chacun.

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


Plus

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

Il est évident que pipe() est plus puissant que 151910920" et il semble que l'ancien ne peut rien faire ce dernier peut faire. Une raison d'utiliser then() pourrait être que son nom reflète son rôle en tant que terminaison d'une chaîne de fonctions même les données.

mais y a-t-il un cas d'utilisation qui nécessite then() 's retournant l'original Deferred qui ne peut pas être fait avec pipe() en raison de lui retourner un nouveau Promise ?

94
demandé sur Community 2012-03-06 16:32:52

3 réponses

Depuis jQuery 1.8 .then se comporte de la même façon que .pipe :

avis de dépréciation: à partir de jQuery 1.8, la méthode deferred.pipe() est dépréciée. La méthode deferred.then() , qui la remplace, devrait être utilisée à la place.

et

à partir de jQuery 1.8 , la méthode deferred.then() renvoie une nouvelle promesse qui peut filtrer le statut et les valeurs d'un différé à travers une fonction, en remplaçant la méthode maintenant dépréciée deferred.pipe() .

les exemples ci-dessous peuvent encore être utiles à certains.


ils ont des buts différents:

  • .then() doit être utilisé chaque fois que vous voulez travailler avec le résultat du processus, c.-à-d. comme la documentation dit, lorsque l'objet différé est résolu ou rejeté. Il est identique à l'utilisation de .done() ou .fail() .

  • Vous pouvez utiliser .pipe() à (pré) filtre le résultat d'une certaine manière. La valeur de retour d'un callback vers .pipe() sera transmise comme argument aux callbacks done et fail . Il peut également retourner un autre objet différé et les callbacks suivants seront enregistrés sur ce différé.

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

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


exemple 1

le résultat d'une certaine opération est un tableau d'objets:

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

et vous voulez calculer le minimum et le maximum des valeurs. Supposons que nous utilisions deux 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" */ 

});

dans les deux cas, vous devez itérer sur la liste et extraire la valeur de chaque objet.

ne vaudrait-il pas mieux extraire valeurs à l'avance afin que vous ne devez pas faire cela dans les deux callbacks individuellement? Oui! Et c'est ce que nous pouvons 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" */

});

évidemment c'est un exemple inventé et il y a beaucoup de différentes (peut-être mieux) façons de résoudre ce problème, mais j'espère qu'il illustre le point.


exemple 2

considère les appels Ajax. Parfois, vous voulez lancer un appel Ajax après un le précédent est terminé. Une façon est de faire le deuxième appel à l'intérieur d'un done callback:

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

laisse maintenant supposer que vous voulez découpler votre code et mettre ces deux appels Ajax dans 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 aimeriez utiliser l'objet différé pour permettre à un autre code qui appelle makeCalls de joindre les callbacks pour le second appel Ajax, mais

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

n'aurait pas l'effet désiré puisque le second appel est effectué à l'intérieur d'un done et non accessible de l'extérieur.

la solution serait d'utiliser .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 permettre d'ajouter des callbacks à L'appel Ajax" interne " sans exposer le flux/ordre réel des appels.


en général, les articles différés fournissent intéressante façon de découpler votre code:)

102
répondu Felix Kling 2013-02-14 11:23:50

il n'y a aucun cas où vous devez utiliser then() au-dessus de pipe() . Vous pouvez toujours choisir d'ignorer la valeur pipe() passe en. Il pourrait être un léger succès de performance pour l'utilisation pipe -- mais il est peu probable d'importance.

donc il pourrait sembler que vous pourriez simplement toujours utiliser pipe() dans les deux cas. Toutefois , en utilisant pipe() , vous communiquez à d'autres personnes de la lecture votre code (y compris vous-même, dans six mois) qu'il y a une certaine importance à la valeur de retour. Si vous le rejetez, vous violez cette construction sémantique.

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

donc utilisez then() quand vous devriez, et pipe() quand vous devriez...

6
répondu Alex Feinman 2012-06-18 19:19:13

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

à Partir de un commentaire de jaubourg jQuery dans le bug tracker ticket #11010 "FAIRE DIFFÉRÉ.ALORS = = DIFFÉRÉ.PIPE LIKE PROMISE/A":

en 1.8, nous retirerons l'ancien alors et remplacerons avec le tuyau actuel. mais la très triste conséquence est que nous devrons dire aux gens d'utiliser le non-standard fait, échec et progrès, parce que la proposition ne fournit pas simple, efficace, signifie simplement ajouter un rappel.

(emphasis mine)

5
répondu hippietrail 2012-10-19 05:59:43