jQuery : Retourner les données après le succès de l'appel ajax

J'ai quelque chose comme ceci, où il s'agit d'un simple appel à un script qui me renvoie une valeur, une chaîne...

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

mais si j'appelle quelque chose comme ceci

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; 
}

**Note : cette réponse a été rédigée en février 2010. Voir les mises à jour de 2015, 2016 et 2017 en bas de page. Vous ne pouvez rien retourner 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 :

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, la faire circuler, l'utiliser comme argument dans les appels de fonction et la renvoyer à partir des fonctions, mais lorsque vous voulez finalement utiliser les 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 moment-là, cette fonction sera invoquée immédiatement. Si elles ne le sont pas, elle sera invoquée dès que les données seront disponibles. Le but de tout cela est que vos données ne soient pas disponibles immédiatement après l'appel à $.ajax, car il est asynchrone. Les promesses sont une belle abstraction pour que les fonctions puissent dire : Je ne peux pas vous renvoyer les données parce que je ne les ai pas encore et je ne veux pas bloquer et vous faire attendre, alors voici une promesse à la place et vous pourrez l'utiliser plus tard, ou la donner à quelqu'un d'autre et en finir avec elle. Voir ce [DEMO] (http://jsfiddle.net/jW68r/). MISE À JOUR (2015)

Actuellement (en mars 2015), les promesses jQuery ne sont pas compatibles avec la [spécification Promises/A+] (http://promises-aplus.github.io/promises-spec/), ce qui signifie qu'elles peuvent ne pas coopérer très bien avec d'autres implémentations conformes à [Promises/A+] (https://github.com/promises-aplus/promises-spec/blob/master/implementations.md). Cependant, les promesses de jQuery dans la prochaine version 3.x seront compatibles avec la spécification Promises/A+ (merci à Benjamin Gruenbaum pour l'avoir signalé). Actuellement (en 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 jQuery Deferred Objects pour faire quelque chose de manière asynchrone qui, dans un code synchrone, serait réalisé en renvoyant une valeur. Mais un appel de fonction synchrone peut faire deux choses : soit renvoyer une valeur (s'il le peut), soit lever une exception (s'il ne peut pas renvoyer une valeur). Promises/A+ traite ces deux cas d'utilisation d'une manière qui est à peu près aussi puissante que la gestion des exceptions dans le code synchrone. La version jQuery gère très bien l'équivalent du retour d'une valeur, mais l'équivalent du traitement complexe des exceptions est quelque peu problématique. En particulier, l'intérêt de la gestion des exceptions dans le code synchrone n'est pas d'abandonner avec un beau message, mais d'essayer de résoudre le problème et de continuer l'exécution, ou éventuellement de relancer la même exception ou une exception différente pour que d'autres parties du programme la gèrent. Dans un code synchrone, vous avez une pile d'appels. Dans un appel asynchrone, ce n&#8217est pas le cas et la gestion avancée des exceptions dans vos promesses, comme l&#8217exige la spécification Promises/A+, peut vraiment vous aider à écrire un code qui gérera les erreurs et les exceptions de manière significative, même dans des cas d&#8217utilisation complexes. Pour les différences entre jQuery et d'autres implémentations, et pour savoir comment convertir les promesses jQuery en promesses conformes à Promises/A+, voir Coming from jQuery par Kris Kowal et al. sur le wiki de la bibliothèque Q et Promises arrive in JavaScript par Jake Archibald sur HTML5 Rocks.

Comment retourner une vraie promesse

La fonction de mon exemple ci-dessus :

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

renvoie un objet jqXHR, qui est un [objet différé] jQuery (https://api.jquery.com/category/deferred-object/). Pour qu'elle renvoie une vraie promesse, vous pouvez la changer 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"
  }));
}

Ce Promise.resolve($.ajax(...)) est également 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 es6-promise module's polyfill() par Jake Archibald. Pour voir où vous pouvez utiliser les promesses ES6 sans le polyfill, voir : Puis-je utiliser : Promesses. Pour plus d'informations, voir :

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

vous pouvez écrire :

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

ou en utilisant l'API Promises/A+ :

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

N'oubliez pas de toujours utiliser des gestionnaires de rejet soit avec :

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

soit avec :

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

Consultez cette réponse pour savoir pourquoi vous devez toujours utiliser les gestionnaires de rejet avec les promesses :

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

Tous les navigateurs ne prennent pas encore en charge cette syntaxe, mais il existe certains cas où vous êtes sûr du navigateur sur lequel votre code sera exécuté, par exemple lorsque vous écrivez une [extension Chrome] (https://developer.chrome.com/extensions/getstarted), un [module complémentaire Firefox] (https://developer.mozilla.org/en-US/Add-ons) ou une application de bureau utilisant Electron, NW.js ou AppJS (voir [cette réponse] (https://stackoverflow.com/questions/35803346/i-want-to-use-nodejs-as-front-end-and-back-end-in-my-application-can-you-sugges/35888163#35888163) pour plus de détails). Pour la prise en charge des fonctions de flèche, voir :

  • Il y a une syntaxe encore plus récente en ce moment appelée fonctions asynchrones avec un nouveau mot clé await qui au lieu de ce code :
functionReturningPromise()
    .then(data => console.log('Data:', data))
    .catch(error => console.log('Error:', error));

vous pouvez écrire :

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

Vous ne pouvez l'utiliser qu'à l'intérieur d'une fonction créée avec le mot-clé async. Pour plus d'informations, voir :

Commentaires (9)
Solution

La seule façon de renvoyer les données de la fonction serait d'effectuer un appel synchrone au lieu d'un appel asynchrone, mais cela bloquerait le navigateur pendant qu'il attend la réponse.

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

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

Appelez-la comme ceci :

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.
Commentaires (7)

Voir l'exemple dans la documentation de jquery : http://api.jquery.com/jQuery.ajax/ (environ 2/3 de la page)

Vous recherchez peut-être le code suivant :

    $.ajax({
     url: 'ajax/test.html',
     success: function(data) {
     $('.result').html(data);
     alert('Load was performed.');
   }
});

Même page... plus bas.

Commentaires (0)