2009-04-02 18 views
33

Tengo una aplicación que estoy escribiendo que modifica los datos en un objeto en caché en el servidor. Las modificaciones se realizan a través de una llamada ajax que básicamente actualiza las propiedades de ese objeto. Cuando el usuario termina de trabajar, tengo un botón básico para 'Guardar cambios' que les permite guardar los datos y vaciar el objeto en caché.jQuery llamada Ajax - Establecer valor de variable en caso de éxito

Para proteger al usuario, quiero advertirles si intentan navegar fuera de la página cuando se han realizado modificaciones en el objeto del servidor si no se han guardado. Entonces, creé un método de servicio web llamado IsInitialized que devolverá verdadero o falso según se hayan guardado o no los cambios. Si no se han guardado, quiero avisar al usuario y darles la oportunidad de cancelar su solicitud de navegación.

Aquí está mi problema - aunque tengo las llamadas funcionando correctamente, parece que no puedo obtener la llamada exitosa ajax para establecer el valor de la variable en su función de devolución de llamada. Aquí está el código que tengo ahora.

////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."; 
    } 
} 

Siento que podría estar intentando utilizar la devolución de llamada de Success de forma inadecuada. ¿Cómo configuro una variable de javascript en la devolución de llamada de Success para poder decidir si se debe solicitar o no al usuario con el mensaje de cambios no guardado?

Como acabo de señalar, estoy realizando una llamada asincrónica, lo que significa que se llama al resto del código antes de que regrese mi método. ¿Hay alguna forma de usar esa llamada ajax, pero aún así atrapar el evento window.onunload? (sin hacer sincronismos ajax)

+0

Acabo de recibir un correo electrónico diciendo que una pregunta mía desde los 5 años pasado fue "marcado como duplicado". La pregunta "original" tiene solo un año. ¡Máquinas de tiempo go-go! :) Es una respuesta más profunda. – Nathan

Respuesta

32

Como necesita este comportamiento en el evento de descarga, tendrá que realizar una llamada síncrona. Sin embargo, puede congelar la ventana/pestaña del navegador dependiendo de cuánto tiempo durará la llamada, pero como está intentando evitar que el usuario cierre la ventana ...

Agregue async: false a su JSON para realizar una llamada síncrona .

4

El hecho es que la solicitud a la llamada Ajax es asincrónica. Entonces, cuando está revisando su inicialización, la llamada aún no ha terminado.

Sugiero que especifique su comportamiento en la función de éxito.

Básicamente tener llamadas síncronas con ajax es, si no imposible, realmente desalentado.

+0

¿Alguna sugerencia sobre cómo puedo atrapar esa ventana aún antes de descargar el evento utilizando la llamada asincrónica? – Nathan

2

En teoría, podría matar el evento (devolver falso) y cerrar la ventana en caso de éxito, pero creo que se encontrarían con restricciones de Javascript establecidas por algunos usuarios y también confundirlos con por qué su ventana no se está cerrando. Entonces, estoy de acuerdo con Pawel Krakowiak, la llamada ajax en sí misma debe ser sincrónica.

Voy a agregar que querrá darle al usuario una notificación de que está revisando el estado (no una ventana emergente, por favor, uno de esos bonitos banners de notificación en la parte superior de la ventana) y asegúrese de establecer la opción de "timeout" de $ .ajax a algo más razonable para esta situación, por lo que no esperan a que la ventana se cierre para siempre.

+0

+1, estuvo de acuerdo con la notificación. Buen punto. –

1

Parece que el mejor enfoque para mí fue utilizar la opción async: false en mi llamada ajax. Aunque entiendo las dudas de Rashack para hacer esto, creo que esta situación justifica los medios.

También es un buen punto de Jerph para asegurarnos de no dejar al usuario colgado mientras trato de verificar su estado. Esa opción acoplada w/the timeout es importante.

Gracias a todos los que han comentado.

2

He tenido un problema similar con el intento de establecer una propiedad de un objeto de datos a través de la devolución de llamada de éxito de una petición Ajax. Usar async: false tampoco resolvió mi problema. Lo que terminé haciendo era utilizar una llamada setTimeout fuera de la llamada AJAX, y establecer el valor de tiempo de espera a 1, así:

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

El solo hecho de que el retraso de 1 milisegundo hizo toda la diferencia en el mundo. Sin él, la propiedad sessionid no se establecería fuera de la llamada ajax, aunque las alertas dentro de la devolución de llamada mostraban que, de hecho, se estaba configurando. Es algo en lo que pensar si surge un problema similar.

Cuestiones relacionadas