web-dev-qa-db-fra.com

JavaScript: variables globales après les requêtes Ajax

la question est assez simple et technique:

var it_works = false;

$.post("some_file.php", '', function(data) {

     it_works = true;

});

alert(it_works); # false (yes, that 'alert' has to be here and not inside $.post itself)

Ce que je veux réaliser, c'est:

alert(it_works); # true

Y-a-t-il un moyen de faire ça? Sinon, $.post() peut-il renvoyer une valeur à appliquer à it_works?

47
Gal

Ce que vous attendez est la demande de type synchrone ( blocage).

var it_works = false;

jQuery.ajax({
  type: "POST",
  url: 'some_file.php',
  success: function (data) {
    it_works = true;
  }, 
  async: false // <- this turns it into synchronous
});​

// Execution is BLOCKED until request finishes.

// it_works is available
alert(it_works);

Les demandes sont asynchrones ( non bloquantes) par par défaut ce qui signifie que le navigateur n'attendra pas qu'ils soient terminés pour continuer son travail. C'est pourquoi votre alerte a obtenu un résultat erroné.

Maintenant avec jQuery.ajax vous pouvez éventuellement définir la demande pour qu'elle soit synchrone , ce qui signifie que le script continuera à s'exécuter après la demande est terminée.


La [~ # ~] méthode recommandée [~ # ~] est cependant de refactoriser votre code pour que les données soient passées à une fonction de rappel dès que la requête est terminée. Ceci est préférable car bloquer l'exécution signifie bloquer l'interface utilisateur, ce qui est inacceptable. Faites-le de cette façon:

$.post("some_file.php", '', function(data) {
    iDependOnMyParameter(data);
});

function iDependOnMyParameter(param) {
    // You should do your work here that depends on the result of the request!
    alert(param)
}

// All code here should be INDEPENDENT of the result of your AJAX request
// ...

La programmation asynchrone est légèrement plus compliquée car la conséquence de faire une requête est encapsulé dans une fonction au lieu de suivre l'instruction de demande. Mais le comportement en temps réel que l'expérience de l'utilisateur peut être beaucoup mieux car ils ne verront pas un serveur ou un réseau lent ralentir le navigateur comme s'il s'était écrasé. La programmation synchrone est irrespectueuse et ne doit pas être employé dans des applications utilisées par des personnes.

Douglas Crockford ( Blog YUI )

88
gblazex

AJAX signifie JavaScript asynchrone et XML. Ainsi, la publication sur le serveur se produit hors synchronisation avec le reste de la fonction. Essayez plutôt du code comme celui-ci (il rompt simplement le raccourci $.post dans le plus long $.ajax appelle et ajoute l'option async).

var it_works = false;

$.ajax({
  type: 'POST',
  async: false,
  url: "some_file.php",
  data: "",
  success: function() {it_works = true;}
});

alert(it_works);

J'espère que cela t'aides!

6
mattbasta

Il semble que votre problème soit simplement un problème de concurrence. La fonction post prend un argument de rappel pour vous indiquer quand la publication est terminée. Vous ne pouvez pas lancer l'alerte dans une portée globale comme celle-ci et vous attendre à ce que la publication soit déjà terminée. Vous devez le déplacer vers la fonction de rappel.

5
Hosam Aly

La raison pour laquelle votre code échoue est que post() lancera une requête asynchrone au serveur. Ce que cela signifie pour vous, c'est que post() retourne immédiatement, pas une fois la requête terminée, comme vous vous y attendez.

Il vous faut donc que la demande soit synchrone et bloque le thread actuel jusqu'à ce que la demande soit terminée. Ainsi,

var it_works = false;

$.ajax({
  url: 'some_file.php',
  async: false,  # makes request synchronous
  success: function() {
    it_works = true;
  }
});

alert(it_works);
2
Jesse Dhillon