web-dev-qa-db-fra.com

jQuery: retourne les données après le succès d'un appel ajax

J'ai quelque chose comme ça, où c'est un simple appel à un script qui me rend une valeur, une chaîne ..

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {
         return data; 
      }
   });
}

mais si j'appelle quelque chose comme ça

var output = testAjax(svar);  // output will be undefined...

alors comment puis-je retourner la valeur? le code ci-dessous ne semble pas fonctionner non plus ...

function testAjax() {
    $.ajax({
      url: "getvalue.php",  
      success: function(data) {

      }
   });
   return data; 
}
435
Francesco

Le seul moyen de renvoyer les données de la fonction serait de passer un appel synchrone au lieu d'un appel asynchrone, mais cela gelerait le navigateur en attendant la réponse.

Vous pouvez transmettre une fonction de rappel qui gère le résultat:

function testAjax(handleData) {
  $.ajax({
    url:"getvalue.php",  
    success:function(data) {
      handleData(data); 
    }
  });
}

Appelez ça comme ça:

testAjax(function(output){
  // here you use the output
});
// Note: the call won't wait for the result,
// so it will continue with the code here while waiting.
364
Guffa

Remarque: cette réponse a été écrite en février 2010.
Voir les mises à jour de 2015, 2016 et 2017 en bas.

Vous ne pouvez rien renvoyer d'une fonction asynchrone. Ce que vous pouvez retourner est une promesse . J'ai expliqué comment les promesses fonctionnent dans jQuery dans mes réponses à ces questions:

Si vous pouviez expliquer pourquoi voulez-vous renvoyer les données et que voulez-vous en faire plus tard, je pourrais peut-être vous donner une réponse plus spécifique comment le faire.

Généralement, au lieu de:

function testAjax() {
  $.ajax({
    url: "getvalue.php",  
    success: function(data) {
      return data; 
    }
  });
}

vous pouvez écrire votre fonction testAjax comme ceci:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

Ensuite, vous pouvez obtenir votre promesse comme ceci:

var promise = testAjax();

Vous pouvez stocker votre promesse, vous pouvez la transmettre, vous pouvez l'utiliser comme argument dans les appels de fonction et vous pouvez la renvoyer à partir de fonctions, mais lorsque vous souhaitez enfin , utilisez vos données renvoyées par l'appel AJAX, vous devez procéder comme suit:

promise.success(function (data) {
  alert(data);
});

(Voir les mises à jour ci-dessous pour une syntaxe simplifiée.)

Si vos données sont disponibles à ce stade, cette fonction sera appelée immédiatement. Si ce n'est pas le cas, il sera invoqué dès que les données seront disponibles.

L'intérêt de tout cela est que vos données ne sont pas disponibles immédiatement après l'appel à $ .ajax car elles sont asynchrones. Promises est une abstraction intéressante pour les fonctions qui disent: Je ne peux pas vous retourner les données car je ne les ai pas encore et je ne veux pas vous bloquer et vous faire attendre. Voici donc une promesse au lieu de cela et vous pourrez l'utiliser plus tard, ou simplement le donner à quelqu'un d'autre et en finir avec.

Voir ceci DÉMO .

MISE À JOUR (2015)

Actuellement (en mars 2015), jQuery Promises n'est pas compatible avec la spécification Promises/A + , ce qui signifie qu'elles ne coopèrent peut-être pas très bien avec d'autres implémentations promesses/A + conformes .

Cependant, jQuery Promises dans la prochaine version 3.x sera compatible avec la spécification Promises/A + (grâce à Benjamin Gruenbaum pour en le faisant remarquer). Actuellement (à partir de mai 2015), les versions stables de jQuery sont 1.x et 2.x.

Ce que j'ai expliqué ci-dessus (en mars 2011) est un moyen d'utiliser Objets différés jQuery pour effectuer une opération asynchrone qui, dans un code synchrone, serait obtenue en renvoyant une valeur.

Mais un appel de fonction synchrone peut faire deux choses: il peut renvoyer une valeur (s’il le peut) ou émettre une exception (s’il ne peut pas renvoyer une valeur). Promises/A + répond à ces deux cas d'utilisation d'une manière aussi puissante que la gestion des exceptions dans le code synchrone. La version jQuery gère l'équivalent de renvoyer une valeur correctement, mais l'équivalent de la gestion complexe des exceptions est quelque peu problématique.

En particulier, le point entier de la gestion des exceptions dans le code synchrone ne consiste pas simplement à abandonner un message de Nice, mais à tenter de résoudre le problème et de poursuivre l’exécution, ou éventuellement de renverser la même exception ou une exception différente pour certaines autres parties du programme manipuler. En code synchrone, vous avez une pile d'appels. Dans les appels asynchrones, la gestion avancée des exceptions dans les promesses, comme l'exige la spécification Promises/A +, peut réellement vous aider à écrire du code qui gérera les erreurs et les exceptions de manière significative, même pour des cas d'utilisation complexes.

Pour connaître les différences entre jQuery et d'autres implémentations et savoir comment convertir les promesses de jQuery en promesses conformes à Promises/A +, voir En provenance de jQuery de Kris Kowal et al. sur le wiki de la bibliothèque Q et Les promesses arrivent en JavaScript par Jake Archibald sur HTML5 Rocks.

Comment rendre une vraie promesse

La fonction de mon exemple ci-dessus:

function testAjax() {
  return $.ajax({
      url: "getvalue.php"
  });
}

retourne un objet jqXHR, qui est un jQuery objet différé .

Pour que cela retourne une vraie promesse, vous pouvez le changer en - en utilisant la méthode du wiki Q :

function testAjax() {
  return Q($.ajax({
      url: "getvalue.php"
  }));
}

ou, en utilisant la méthode de l'article HTML5 Rocks :

function testAjax() {
  return Promise.resolve($.ajax({
      url: "getvalue.php"
  }));
}

Ceci Promise.resolve($.ajax(...)) est aussi ce qui est expliqué dans la documentation du module promise et il devrait fonctionner avec ES6 Promise.resolve() .

Pour utiliser les promesses ES6 aujourd'hui, vous pouvez utiliser polyfill() du module es6-promise de Jake Archibald.

Pour voir où vous pouvez utiliser les promesses ES6 sans le polyfill, voir: Puis-je utiliser: Promises .

Pour plus d'informations, voir:

Avenir de jQuery

Les futures versions de jQuery (à partir de 3.x - les versions stables actuelles à compter de mai 2015 sont 1.x et 2.x) seront compatibles avec la spécification Promises/A + (grâce à Benjamin Gruenbaum pour l'avoir signalé dans les commentaires). "Les deux modifications que nous avons déjà décidées sont la compatibilité Promise/A + pour notre implémentation différée [...]" ( jQuery 3.0 et l'avenir du développement Web ). Pour plus d'informations, voir: jQuery 3.0: les prochaines générations par Dave Methvin et jQuery 3.0: plus d'interopérabilité, moins Internet Explorer par Paul Krill.

Entretiens intéressants

MISE À JOUR (2016)

Il existe une nouvelle syntaxe dans ECMA-262, 6e édition, section 14.2 appelée fonctions de flèche , qui peut être utilisée pour simplifier davantage les exemples ci-dessus.

Utilisation de l'API jQuery au lieu de:

promise.success(function (data) {
  alert(data);
});

tu peux écrire:

promise.success(data => alert(data));

ou en utilisant l'API Promises/A +:

promise.then(data => alert(data));

N'oubliez pas de toujours utiliser les gestionnaires de rejet avec:

promise.then(data => alert(data), error => alert(error));

ou avec:

promise.then(data => alert(data)).catch(error => alert(error));

Voir cette réponse pour voir pourquoi vous devriez toujours utiliser des gestionnaires de rejet avec des promesses:

Bien sûr, dans cet exemple, vous pouvez utiliser uniquement promise.then(alert) car vous appelez simplement alert avec les mêmes arguments que votre rappel, mais la syntaxe de la flèche est plus générale et vous permet d'écrire des choses comme:

promise.then(data => alert("x is " + data.x));

Tous les navigateurs ne supportent pas encore cette syntaxe, mais dans certains cas, vous êtes sûr du navigateur sur lequel votre code sera exécuté - par exemple. lors de l'écriture d'un extension Chrome , d'un complément Firefox , ou d'une application de bureau utilisant Electron, NW.js ou AppJS (voir cette réponse pour détails).

Pour le support des fonctions de flèche, voir:

MISE À JOUR (2017)

Il existe actuellement une syntaxe encore plus récente, appelée fonctions asynchrones, avec un nouveau mot clé await au lieu de ce code:

functionReturningPromise()
    .then(data => console.log('Data:', data))
    .catch(error => console.log('Error:', error));

vous permet d'écrire:

try {
    let data = await functionReturningPromise();
    console.log('Data:', data);
} catch (error) {
    console.log('Error:', error);
}

Vous ne pouvez l'utiliser que dans une fonction créée avec le mot clé async. Pour plus d'informations, voir:

Pour le support dans les navigateurs, voir:

Pour le support dans Node, voir:

Dans les endroits où vous n'avez pas de support natif pour async et await, vous pouvez utiliser Babel:

ou avec une syntaxe légèrement différente, une approche basée sur un générateur comme dans co ou Bluebird:

Plus d'informations

Quelques autres questions sur les promesses pour plus de détails:

387
rsp

vous pouvez ajouter l'option async à false et retourner en dehors de l'appel ajax.

function testAjax() {
    var result="";
    $.ajax({
      url:"getvalue.php",
      async: false,  
      success:function(data) {
         result = data; 
      }
   });
   return result;
}
174
Ging3r

Idk si vous l'avez résolu mais je recommande une autre façon de le faire, et ça marche :)

    ServiceUtil = ig.Class.extend({
        base_url : 'someurl',

        sendRequest: function(request)
        {
            var url = this.base_url + request;
            var requestVar = new XMLHttpRequest();
            dataGet = false;

            $.ajax({
                url: url,
                async: false,
                type: "get",
                success: function(data){
                    ServiceUtil.objDataReturned = data;
                }
            });
            return ServiceUtil.objDataReturned;                
        }
    })

Donc, l’idée principale ici est que, en ajoutant async: false, tout est mis en attente jusqu’à ce que les données soient récupérées. Ensuite, vous l'assignez à une variable statique de la classe, et tout fonctionne comme par magie :)

0
user1509803