3 votes

Meilleures pratiques pour la mise en œuvre de la programmation asynchrone en javascript avec la bibliothèque promise Q

J'ai déjà une couche en JS qui aide les Gets et les Posts au serveur avec les implémentations suivantes :

var getJson = function(url, callback, onError) {
    $.get(url)
    .done(function(data) {
        if(callback != null)
            callback(data);
    })
    .fail (function(error) {
        if(onError != null)
            onError (error);
        else
            my.notification.notifyError(onErrorMessage);
    });
};

var postJSON = function(url, data, callback, onError) {
    $.ajax({
        url : url ,
        type: "POST" ,
        contentType : "application/json"
        dataType : "json" ,
        date : ko.toJSON(data)
    })
    .done(function(data) {
        if(callback ! = null)
            callback(data);
    })
    .fail(function(error) {
        if(onError ! = null)
            onError (error);
        else
            my.notification.notifyError(onErrorMessage);
    });
};

Utilisation de ces implémentations sur la couche DataService :

// Get
var find = function(date, onSuccess , onError) {
   var url = /* url with the Controller and Action */ + "?queryString = " + data.filter;
   getJson(url , onSuccess , onError);
};

// Post
var save = function(date, onSuccess , onError) {
    var url = /* url with the Controller and Action */;
    postJSON(url, data, onSuccess, onError);
};

Cependant nous utilisons des webapi, qui dans certains cas, une requête dépend du résultat d'une autre requête générant une "Pyramide du Destin". Pour plus d'élégance du code nous implémentons la bibliothèque Q pour la programmation asynchrone.

Pour suivre le modèle montré ci-dessus en utilisant Q promisses a été mis en œuvre une nouvelle méthode de get as show :

var getJsonDefer = function(url, callback, onError) {
    return Q.when($.getJSON(url))
    .then (function(data) {
        if(callback ! = null)
            callback(data);
    })
    .fail (function(error) {
        if(onError ! = null)
            onError (error);
        else
            my.notification.notifyError(onErrorMessage);
    });
};

J'essaie d'utiliser cette mise en œuvre sur la couche DataService de cette façon :

// Get
var find = function(date, onSuccess , onError) {
   var url = /* url with the Controller and Action */ + "?queryString = " + data.filter;
   return getJsonDefer(url, onSuccess, onError);
};

Quoi qu'il en soit, dans ma couche viewmodel javascript, je suppose que je dois utiliser 3 recherches et que l'une dépend du résultat de l'autre :

var = dataOne { 
    filter: " Filter"
};

findOne(dataOne,
       function(result) {
            return result;
       }
       function(error) {
           throw error;
       })
       .then(function(args) {
            var = datatwo { 
                filter: args
            };

            // Second
            findTwo(datatwo ,
               function(result) {
                    return result;
               }
               function(error) {
                   throw error;
               }
            );
        })
        .then(function(args) {
            var = dataThree { 
                filter: args
            };

            // Third
            findThree(dataThree,
                function(result) {
                    return result;
                }
                function(error) {
                    throw error;
                }
            );
        }).catch(function(error) {
            // Handle any error from all above steps
        })
        .done();

Mon problème :

J'admets que je ne suis pas en mesure de mettre en œuvre la bonne méthode, parce que toutes mes fonctions à l'intérieur de .then() viennent avec des arguments non définis.

Je me demande quelle est la meilleure pratique pour répondre au scénario proposé ici.

2voto

Kris Kowal Points 1845

Je pense que vous trouverez que l'intérêt des promesses est que vous pouvez atteindre vos objectifs avec beaucoup moins de code qu'auparavant. Il y a cependant quelques points que vous devez connaître. Tout d'abord, vous n'aurez plus besoin de passer ou de recevoir des callbacks et des errbacks. Vous devez simplement vous assurer de renvoyer des résultats ou des promesses de résultats dans vos gestionnaires. C'est ainsi que les valeurs se propagent vers le gestionnaire suivant.

Il s'agit d'une adaptation non testée de votre programme qui devrait illustrer le formulaire :

var find = function(data) {
    var url = /* url with the Controller and Action */ + "?queryString = " + data.filter;
    return Q($.getJson(url));
};

find({filter: "filter"})
.then(function (firstResult) {
    return find({filter: firstResult})
    .then(function (secondResult) {
        return find({filter: secondResult})
        .then(function (thirdResult) {
            return [firstResult, secondResult, thirdResult];
        });
    });
})
.fail(notifyError)
.done();

Notez qu'une erreur dans n'importe quelle étape sera gérée par l'unique fail appel en bas de page. Que vous ayez ou non un gestionnaire d'erreur à la fin, terminez toujours une chaîne par done() de sorte que toutes les erreurs qui se produisent avant, même dans votre fail s'affichent dans votre console.

Notez que vous n'avez besoin d'imbriquer les promesses que si une opération dépend de la précédente et que le gestionnaire doit accéder à la fois au premier et au second résultat. Si vous n'avez besoin que du résultat de la deuxième opération, vous pouvez simplement enchaîner.

find({filter: "filter"})
.then(function (firstResult) {
    return find({filter: firstResult})
})
.then(function (secondResult) {
    return find({filter: secondResult})
    .then(function (thirdResult) {
        return [secondResult, thirdResult];
    });
});
.fail(notifyError)
.done();

Vous pouvez également aplatir les choses avec Q.all y promise.spread mais je vous laisse à la documentation à ce stade parce que, j'espère, vous avez compris l'essentiel.

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