2009-04-02 11 views
33

Ho un'applicazione che sto scrivendo che modifica i dati su un oggetto memorizzato nella cache nel server. Le modifiche vengono eseguite tramite una chiamata ajax che sostanzialmente aggiorna le proprietà di quell'oggetto. Quando l'utente ha terminato di lavorare, ho un pulsante "Salva modifiche" di base che consente loro di salvare i dati e svuotare l'oggetto memorizzato nella cache.jQuery chiamata Ajax - Imposta il valore variabile in caso di successo

Per proteggere l'utente, desidero avvisarlo se si tenta di spostarsi dalla pagina quando le modifiche sono state apportate all'oggetto server se non sono state salvate. Quindi, ho creato un metodo di servizio Web denominato IsInitialized che restituirà true o false in base al fatto che siano state salvate o meno modifiche. Se non sono stati salvati, voglio chiedere all'utente e dare loro la possibilità di cancellare la loro richiesta di navigazione.

Ecco il mio problema: anche se le chiamate funzionano correttamente, non riesco a ottenere la chiamata di successo ajax per impostare il valore della variabile sulla sua funzione di callback. Ecco il codice che ho ora.

////Catches the users to keep them from navigation off the page w/o saved changes... 
window.onbeforeunload = CheckSaveStatus; 
var IsInitialized; 

function CheckSaveStatus() { 

    var temp = $.ajax({ 
     type: "POST", 
     url: "URL.asmx/CheckIfInstanceIsInitilized", 
     data: "{}", 
     contentType: "application/json; charset=utf-8", 
     dataType: "json", 
     success: function(result) { 
      IsInitialized = result.d; 
     }, 
     error: function(xmlHttpRequest, status, err) { 
      alert(xmlHttpRequest.statusText + " " + xmlHttpRequest.status + " : " + xmlHttpRequest.responseText); 
     } 

    }); 

    if (IsInitialized) { 
     return "You currently have unprocessed changes for this Simulation."; 
    } 
} 

Sento che potrei provare a utilizzare la richiamata Success in modo inappropriato. Come faccio a impostare una variabile javascript sul callback Success in modo che possa decidere se l'utente debba o meno essere invitato w/il messaggio di modifiche non salvate?

Come è stato appena sottolineato, sto effettuando una chiamata asincrona, il che significa che il resto del codice viene chiamato prima che il metodo restituisca. C'è un modo per usare quella chiamata ajax, ma catturare comunque l'evento window.onunload? (senza sincronizzare ajax)

+0

Sono appena una e-mail dicendo che una mia domanda dai 5 anni passati è stato "contrassegnato come duplicato". La domanda "originale" ha solo un anno. Macchine del tempo go-go! :) È una risposta più approfondita. – Nathan

risposta

32

Poiché è necessario questo comportamento nell'evento di scaricamento, sarà necessario effettuare una chiamata sincrona. Tuttavia, potrebbe bloccare la finestra o la scheda del browser in base alla durata della chiamata, ma perché stai effettivamente cercando di impedire all'utente di chiudere la finestra ...

Aggiungi async: false al tuo JSON per effettuare una chiamata sincrona .

4

Il fatto è che la richiesta di chiamata Ajax è asincrona. Pertanto, quando si verifica IsInitialized, la chiamata non è ancora terminata.

Suggerisco di specificare il proprio comportamento nella funzione riuscita.

Sostanzialmente le chiamate sincrone con ajax sono se non impossibili di quelle realmente scoraggiate.

+0

Qualche suggerimento su come posso ancora catturare quell'evento window.onbeforeunload utilizzando la chiamata asincrona? – Nathan

2

Si potrebbe teoricamente uccidere l'evento (restituire false) e chiudere la finestra in caso di successo, ma penso che si verifichino le restrizioni Javascript impostate da alcuni utenti e anche solo confonderle sul motivo per cui la loro finestra non si sta chiudendo. Quindi, sono d'accordo con Pawel Krakowiak, la stessa chiamata ajax deve essere sincrona.

Aggiungo che vorrai dare all'utente una notifica che stai controllando lo stato (non un popup, per favore, uno di quei begli banner di notifica nella parte superiore della finestra) e assicurati di impostare l'opzione $ .ajax "timeout" a qualcosa di più ragionevole per questa situazione, quindi non stanno aspettando per sempre che la finestra si chiuda.

+0

+1, concordato sulla notifica. Buon punto –

1

Sembra che l'approccio migliore per me è stato utilizzare l'opzione asincrona: false sulla mia chiamata ajax. Sebbene comprendo l'esitazione di Rashack per questo, penso che questa situazione giustifica i mezzi.

Un altro aspetto importante di Jerph è quello di assicurarsi di non lasciare l'utente in sospeso mentre sto cercando di verificare il loro stato. Quella accoppiata con l'opzione di timeout è importante.

Grazie a tutti coloro che hanno commentato.

2

Ho avuto un problema simile con il tentativo di impostare una proprietà per un oggetto di dati attraverso la richiamata successo di una richiesta AJAX. L'utilizzo di async: false non ha risolto neanche il mio problema. Quello che ho finito per fare è stato quello di utilizzare un setTimeout chiamata esterna chiamata AJAX, e impostare il valore di timeout a 1, in questo modo:

function getSessionid() { 
    $.ajax({ 
     type: 'POST', 
     url: 'getSession.php', 
     dataType: 'text', 
     success: function(result){myData.sessionid = result;}, 
     error: function(data) {alert("Error!\n" + data);} 
    }); 
    setTimeout(function() {alert('sessionid = ' + myData.sessionid);},1); 
} 

Basta avere che il ritardo di 1 millisecondo fatto tutta la differenza del mondo. Senza di esso, la proprietà sessionid non verrà impostata all'esterno della chiamata ajax, sebbene gli avvisi all'interno del callback mostrino che è stato effettivamente impostato. È qualcosa a cui pensare, se dovessi affrontare un problema simile.