2010-07-11 22 views
35

la questione è abbastanza semplice e tecnica:JavaScript: Le variabili globali dopo Ajax richieste

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) 

Quello che voglio ottenere è:

alert(it_works); # true 

C'è un modo per farlo? In caso contrario, $.post() può restituire un valore da applicare a?

+3

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

risposta

69

Quello che ci si aspetta è la sincrono (blocco) tipo di richiesta.

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

Le richieste sono asincrono (non bloccante) per impostazione predefinita il che significa che il browser non attendere per loro di essere completato al fine di continuare il suo lavoro. Ecco perché il tuo avviso ha ottenuto risultati errati.

Ora, con jQuery.ajax è possibile opzionalmente impostare la richiesta di essere sincrona, il che significa che lo script solo continuerà a correre dopo la richiesta è terminata.


Il modo RACCOMANDATO, tuttavia, è quello di refactoring il codice in modo che i dati sarebbero stati passati a un callback funzione non appena la richiesta è terminata. Questo è preferito perché bloccare l'esecuzione significa bloccare l'interfaccia utente che è inaccettabile. Farlo in questo modo:

$.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 programmazione è leggermente più complicata perché la conseguenza di fare una richiesta viene incapsulato in una funzione invece di seguire la dichiarazione richiesta. Ma il comportamento in tempo reale che le esperienze degli utenti possono essere significativamente meglio perché non vedranno un server lento o di rete lenta causano il browser di agire come se fosse caduto. sincrono programmazione è irrispettoso e non dovrebbero essere impiegate in applicazioni che vengono utilizzati da persone.

Douglas Crockford(YUI Blog)

+0

mio cattivo, bastonatemi. – mattbasta

+0

@mattbasta nessun problema :) – galambalazs

+3

Ma si noti che questo ucciderà l'usabilità se 'some_file.php' preforma operazioni molto costose. –

4

Sembra che il tuo problema sia semplicemente un problema di concorrenza. La funzione post accetta un argomento di callback per dirti quando il post è stato completato. Non è possibile rendere l'avviso nell'ambito globale come questo e aspettarsi che il post sia già stato completato. Devi spostarlo sulla funzione di callback.

6

AJAX sta per Asynchronous JavaScript e XML. Pertanto, il post sul server non è sincronizzato con il resto della funzione. Prova invece un codice come questo (interrompe semplicemente la stenografia $.post nella chiamata lunga $.ajax e aggiunge l'opzione async).

var it_works = false; 

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

alert(it_works); 

Spero che questo aiuti!

3

Il motivo per cui il codice non funziona è perché post() avvia una richiesta asynchronous sul server. Quello che significa per te è che post() restituisce immediatamente, non dopo che la richiesta è stata completata, come ci si aspetta.

Quello che serve, quindi, è che la richiesta sia sincrona e blocchi il thread corrente fino al completamento della richiesta. Così,

var it_works = false; 

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

alert(it_works);