web-dev-qa-db-fra.com

Renvoyer des données $ .get dans une fonction utilisant jQuery

J'essaie d'appeler une fonction qui contient du code jQuery. Je veux que cette fonction renvoie les résultats de l'instruction jQuery. Cela ne fonctionne pas et j'essaie de comprendre pourquoi.

function showGetResult (name) {
    var scriptURL = "somefile.php?name=" + name;
    return $.get(scriptURL, {}, function(data) { return data; });
}

alert (showGetResult("John"));

L'alerte affiche "[object XMLHttpRequest]". Cependant, si je lance l'instruction jQuery par elle-même, en dehors d'une fonction, cela fonctionne très bien -> $.get(scriptURL, {}, function(data) { alert(data); })

J'aimerais pouvoir réutiliser ce code en le plaçant dans une fonction qui renvoie les données $.get. Quelle erreur fondamentale est-ce que je fais ici?

33
Kai

Vous avez quelques erreurs différentes. Premièrement, $ .get ne renvoie pas la valeur de retour de la fonction de rappel. Il retourne l'objet XHR. Deuxièmement, la fonction get n'est pas synchrone, elle est asynchrone, donc showGetResult sera probablement renvoyé avant que l'opération ne soit terminée. Troisièmement, vous ne pouvez pas renvoyer quelque chose de l'intérieur du rappel vers l'étendue externe. Vous pouvez toutefois lier une variable dans la portée externe et la définir dans le rappel.

Pour obtenir la fonctionnalité souhaitée, vous devez utiliser $ .ajax et définir l’option async sur false. Vous pouvez ensuite définir une variable dans l'étendue externe et l'affecter dans le rappel ajax, en renvoyant cette variable à partir de la fonction.

function showGetResult( name )
{
     var result = null;
     var scriptUrl = "somefile.php?name=" + name;
     $.ajax({
        url: scriptUrl,
        type: 'get',
        dataType: 'html',
        async: false,
        success: function(data) {
            result = data;
        } 
     });
     return result;
}

Vous seriez probablement mieux servi, cependant, en trouvant comment faire ce que vous voulez dans la fonction de rappel elle-même plutôt que de passer d'appels asynchrones à synchrones.

92
tvanfosson

L'erreur fondamentale que vous commettez est que l'appel AJAX est passé de manière asynchrone. Ainsi, au moment de votre retour, le résultat n'est pas encore prêt. Pour que cela fonctionne, vous pouvez modifier votre code comme ceci:

$(function() {
    showGetResult('John');
});

function showGetResult (name) {
    $.get('somefile.php', { 
        // Pass the name parameter in the data hash so that it gets properly
        // url encoded instead of concatenating it to the url.
        name: name 
    }, function(data) { 
        alert(data); 
    });
}
9
Darin Dimitrov

On dirait que vous voulez une requête synchrone: Comment puis-je obtenir que jQuery exécute une requête Ajax synchrone plutôt qu'asynchrone?

Ou, vous pouvez souhaiter rappeler votre fonction:

function showGetResult (name, callback) {
  var scriptURL = "somefile.php?name=" + name;
  return $.get(scriptURL, {}, callback);
}

showGetResult("John", function(data){ alert(data); });
6
queen3

L'erreur fondamentale est la partie "asynchrone" de AJAX. Parce que vous ne savez pas combien de temps le serveur mettra pour envoyer une réponse, les méthodes AJAX ne «bloquent» jamais - c'est-à-dire que vous n'appelez pas le serveur et attendez le résultat. . Au lieu de cela, vous passez à autre chose, mais vous configurez une méthode, appelée "rappel", qui sera déclenchée lorsque les résultats seront renvoyés. Cette méthode est responsable de tout ce qui doit être fait avec les données (par exemple, en les injectant dans la page).

2
Jacob Mattison

C'est la mauvaise façon de faire. La fonction (data) est une fonction de rappel. Ainsi, chaque fois que return $ .get sera exécuté.

Mieux vous appelez votre fonction post data data from method (data).

1
jatanp

Un moyen efficace consiste à utiliser la méthode différée de jQuery, à la fois les requêtes sync/async au serveur et l'attente de deferred.resolve (), puis de retourner l'objet de promesse différée. Cela semble un peu fastidieux, mais une petite étude est certainement utile pour les données volumineuses. (La fonction de tvanfosson fonctionne bien dans ce cas, mais lorsque je travaillais sur les données d'analyse de Google, une grande quantité d'informations m'a rendu fou et que je devais donc trouver cette solution.)

     function showResults(name) { 
        var deferred = $.Deferred, requests = [];

        requests.Push($.ajax(url:"/path/to/uri/?name=" + name, type: "GET", async: false}).done(function(d) { 
         //alert or process the results as you wish })
        );
        $.when.apply(undefined, requests).then(function() { deferred.resolve(); }); 
        return deferred.promise();

    }

l'objet de promesse retourné peut également être utilisé avec $.when(showResults('benjamin')).done(function() { }); pour les modifications ultérieures (comme les paramètres de graphique/graphique, etc.). totalement réutilisable . Vous pouvez aussi mettre cette fonction dans une boucle de requêtes $ .deferred telles que,

        function updateResults() { 
             var deferred = $.Deferred, requests = [];
             requests.Push($.ajax(url:"/path/to/names/?nameArr=" + jsonArrOfNames, type: "GET", async: false}).done(function(res) {  requests.Push(showResults(res[0]));}) );
             $.when.apply($, requests).then(function() { deferred.resolve(); }); 
             return deferred.promise();
            }
0
Cosmo Arun