web-dev-qa-db-fra.com

Valeur de retour asynchrone JavaScript / affectation avec jQuery

J'ai la fonction jQuery suivante. J'essaie de renvoyer la valeur GUID affichée ici dans la fonction alert(); L'alerte fonctionne bien et la valeur est remplie, mais je n'arrive pas à l'affecter à un variable et retourner sa valeur.

En fin de compte, j'ai besoin d'accéder à la valeur GUID dans d'autres fonctions, etc. Tout ce que j'ai essayé ne s'affiche que sous la forme undefined.

Je voudrais faire quelque chose comme ça:

function trackPage(){
    var elqTracker = new jQuery.elq(459);
    elqTracker.pageTrack({
        success: function() {
            elqTracker.getGUID(function(guid) {
                alert(guid);
                var returnValue = guid;
            });
        }
    });
    return returnValue;
}

var someGuid = trackPage();
28
patrick

Donc, cette question a été posée un million de fois, et je suis sûr que tout le monde (moi y compris) a essayé une fois .

C'est juste la nature d'un appel asynchrone, vous ne pouvez pas utiliser leurs résultats en tant que valeur return. C'est pourquoi ils vous font passer une fonction qui obtient le résultat de l'appel, ils ne peuvent pas non plus return! Notez également que l'appel de fonction elqTracker.pageTrack() renvoie IMMÉDIATEMENT, donc votre returnValue est simplement undefined.

La plupart des gens (voir la réponse de dfsq) résolvent ce problème en introduisant une fonction de rappel comme paramètre. Cette méthode est essayée et vraie - mais jQuery a $.Deferred . Cela vous permet de faire en sorte que votre propre logique asynchrone renvoie un promise auquel vous pouvez ensuite attacher un nombre quelconque de rappels à:

function trackPage(){
    var elqTracker = new jQuery.elq( 459 ),
        dfd = $.Deferred();

    elqTracker.pageTrack({
        success: function() {
            elqTracker.getGUID(function( guid ) {
                dfd.resolve( guid );
            });
        }
    });

    return dfd.promise();
}

// example use:
trackPage().done(function( guid ) {
    alert( "Got GUID:" + guid );
});

Notez maintenant que votre trackPage() renvoie un objet auquel vous pouvez attacher des rappels? Vous n'avez pas non plus à les attacher immédiatement.

var pageHit = trackPage().done(function( guid ) {
    alert( "Page Hit GUID:" +guid );
});

$("button").click(function() {
    pageHit.done( function( guid ) {
        alert( "Clicked on Page GUID:" + guid );
    });
});

De plus, le module jQuery AJAX retourne toujours aussi des promesses, donc l'interface pour tous vos trucs AJAX devrait être très similaire si vous faites vos propres promesses de retour logique .


En guise de remarque: j'aimerais souligner que votre var returnValue N'était de toute façon pas dans la "bonne" portée. Elle devait être déclarée dans la portée externe de la fonction trackPage. Même avec cette correction, le concept ne fonctionne toujours pas.

49
gnarf

Puisque vous avez un appel asynchrone, la façon dont vous essayez d'écrire du code ne fonctionnera pas (car au moment de return returnValue; dans la valeur de retour trackCode n'est pas encore défini). Au lieu de cela, vous devez passer le rappel dans trackPage:

function trackPage(callback) {
    var elqTracker = new jQuery.elq(459);
    elqTracker.pageTrack({
        success: function() {
            elqTracker.getGUID(function(guid) {
                alert(guid);
                // Instead of this: var returnValue = guid;
                // You should use your callback function
                callback(guid);
            });
        }
    });
    return returnValue;
}

trackCode(function(guid) {
    // perform some actions with guid
});
14
dfsq