2010-07-11 10 views
35

la question est assez simple et technique:JavaScript: Les variables globales après Ajax demandes

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 est:

alert(it_works); # true 

Est-il possible de le faire? Si ce n'est pas le cas, $.post() peut-il renvoyer une valeur à appliquer à it_works?

+3

Voir http://stackoverflow.com/questions/133310/how-can-i-get-jquery-to-perform-a-synchronous-rather-than-asynchronous-ajax-req –

Répondre

69

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 bloquant) par défaut ce qui signifie que le navigateur ne sera pas les attendre à remplir afin de poursuivre ses travaux. C'est pourquoi votre alerte a obtenu un mauvais résultat.

Maintenant, avec jQuery.ajax vous pouvez également définir la demande d'être synchrone, ce qui signifie que le script ne continuera à fonctionner après la demande est terminée.


Le RECOMMANDÉ façon, cependant, est de refactor votre code afin que les données seraient transmises à une fonction de rappel dès que la demande 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 
// ... 

Programmation asynchrone est un peu plus compliquée parce que la conséquence de faire une demande est encapsulé dans une fonction au lieu de suivre l'instruction de la demande. Mais le comportement en temps réel que les expériences utilisateur peuvent être considérablement mieux parce qu'ils ne voient pas d'un serveur lent ou d'un réseau lent que le navigateur d'agir comme si elle avait écrasé. La programmation synchrone est irrespectueuse et ne doit pas être utilisée dans les applications qui sont utilisées par des personnes.

Douglas Crockford(YUI Blog)

+0

Mon mauvais, bat moi moi. – mattbasta

+0

@mattbasta pas de problème :) – galambalazs

+3

Mais notez que cela va tuer la facilité d'utilisation si 'some_file.php' préforme beaucoup d'opérations (coûteuses). –

4

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

6

AJAX signifie Asynchronous JavaScript et XML. Ainsi, la publication sur le serveur se désynchronise avec le reste de la fonction. Essayez un code comme celui-ci à la place (il casse simplement le raccourci $.post dans l'appel $.ajax plus long 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); 

Espérons que cela aide!

3

La raison de l'échec de votre code est que post() va lancer une requête asynchronous sur le serveur. Qu'est-ce que cela signifie pour vous, c'est que post() renvoie immédiatement, pas après la fin de la requête, comme vous l'attendez. Vous avez donc besoin que la requête soit synchrone et bloque le thread courant jusqu'à la fin de la requête. Ainsi,

var it_works = false; 

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

alert(it_works);