2010-07-11 7 views
35

die Frage ist ziemlich einfach und technisch:JavaScript: Globale Variablen nach Ajax fordert

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) 

Was will ich erreichen ist:

alert(it_works); # true 

Gibt es eine Möglichkeit, das zu tun? Wenn nicht kann $.post() einen Wert zurückgeben, der auf it_works angewendet wird?

+3

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

Antwort

69

Was Sie erwarten, ist die synchrone (Blockierung) Typ Anfrage.

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

Requests sind asynchrone (nicht blockierende) durch Standard was bedeutet, dass der Browser wartet, nicht für sie, um seine Arbeit fortzusetzen abgeschlossen werden. Deshalb hat Ihre Warnung ein falsches Ergebnis erhalten.

Jetzt, mit jQuery.ajax können Sie optional die Anforderung gesetzt Synchron zu sein, was bedeutet, dass das Skript nur nach die Anfrage weiter laufen, abgeschlossen ist.


Der EMPFOHLEN Weg ist jedoch zu refactor Ihr Code so, dass die Daten an eine Funktion Rückruf geben werden würden, sobald die Anfrage abgeschlossen ist. Dies wird bevorzugt, da die Ausführung von Sperren das Blockieren der UI bedeutet, was nicht akzeptabel ist. Tun Sie es auf diese Weise:

$.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 
// ... 

Asynchronous Programmierung ist etwas kompliziert weil die Folge von einer Anforderung statt in einer Funktion gekapselt ist die Anforderung Anweisung zu folgen. Aber das Echtzeitverhalten, dass die Benutzererfahrungen deutlich besser sein können, weil sie nicht ein träge Server oder träge Netzwerk sehen bewirken, dass der Browser handeln, als ob es abgestürzt war. Synchron Programmierung ist respektlos und sollte nicht in Anwendungen verwendet werden, die von Menschen verwendet werden.

Douglas Crockford(YUI Blog)

+0

Meine Schlimm, schlag mich dazu. – mattbasta

+0

@mattbasta kein Problem :) – galambalazs

+3

Aber beachten Sie, dass dies die Benutzerfreundlichkeit umbringt, wenn 'some_file.php' viele (teure) Operationen durchführt. –

4

Es scheint, dass Ihr Problem einfach ein Nebenläufigkeitsproblem ist. Die post-Funktion akzeptiert ein Callback-Argument, um Ihnen mitzuteilen, wann der Post fertiggestellt wurde. Sie können die Warnung nicht in globalem Umfang wie folgt ausführen und erwarten, dass der Post bereits fertig ist. Sie müssen es in die Rückruffunktion verschieben.

6

AJAX steht für Asynchronous JavaScript and XML. Der Post auf dem Server erfolgt daher nicht synchron mit dem Rest der Funktion. Versuchen Sie stattdessen einen Code wie diesen (er bricht nur die Abkürzung $.post hinaus in den längeren $.ajax Aufruf und fügt die async Option hinzu).

var it_works = false; 

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

alert(it_works); 

Hoffe, das hilft!

3

Der Grund, warum Ihr Code fehlschlägt, ist, weil post() eine asynchronous Anfrage an den Server startet. Was das für Sie bedeutet, ist, dass post() sofort zurückkehrt, nicht, nachdem die Anfrage abgeschlossen ist, wie Sie erwarten.

Sie müssen also synchron sein und den aktuellen Thread blockieren, bis die Anfrage abgeschlossen ist. So

var it_works = false; 

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

alert(it_works);