2010-08-27 4 views
35

Necesito un método para supervisar las sesiones de edición del usuario, y una de las soluciones que estoy revisando me tendrá usando un evento unload para enviar una solicitud ajax para informar al servidor del final de la sesión de edición. (Ver: Monitoring User Sessions to Prevent Editing Conflict)¿Se puede usar el evento de descarga para despedir de manera confiable la solicitud de ajax?

Mi lectura (bastante limitada) del evento unload indica que los códigos adjuntos a este controlador deben ejecutarse rápidamente y, como tal, se utilizan generalmente para borrar objetos y evitar fugas de memoria.

Mi pregunta es, ¿puede esto funcionar de manera confiable para este propósito?

PS. Sé sobre la opción async: false.

Respuesta

35

Este método es bastante confiable, si su servidor es lo suficientemente rápido para responder. Algo para tener realmente cuidado sin embargo. Si cierra el navegador y envía la solicitud de AJAX al evento de descarga, hay muchas posibilidades de que la respuesta no vuelva del servidor a tiempo antes de que se destruya el objeto de la ventana. Lo que sucede en este caso (al menos con IE) es que huérfano su objeto de conexión y no terminarlo correctamente hasta que se llegue al tiempo de espera de la conexión. Si su servidor no tiene activada la conexión keep-alive, después de cerrar 2 ventanas (mientras aún tiene otra ventana abierta), se le acabarán las conexiones abiertas al servidor (para IE6-7, para IE8 - 6 ventanas) y no podrá abrir su sitio web hasta que se agote el tiempo de espera de su conexión.

Me encontré en una situación como esa antes de abrir una ventana emergente que enviaba una solicitud de AJAX en la descarga, era muy confiable, pero estaba plagada por la emisión descrita anteriormente, y tomó mucho tiempo para yo para rastrearlo y entender lo que está pasando. Después de eso, lo que hice, es que me aseguré de que la ventana de apertura tuviera el mismo código para llamar al servidor, y en cada descarga se verificaba el abridor y se ejecutaba el código allí si estaba presente.

Parece que si cierra la última ventana del navegador, IE destruirá la conexión correctamente, pero si hay otra ventana abierta, no lo hará.

P.S. Y solo para comentar la respuesta anterior, AJAX no es realmente asincrónico. Al menos la implementación de JS no lo es. Después de enviar una solicitud, su código JS seguirá esperando la respuesta del servidor. No va a bloquear la ejecución del código, pero dado que el servidor puede tardar un tiempo en responder (o el tiempo suficiente para que Windows rescinda el objeto de la ventana de IE), es probable que se encuentre con el problema descrito anteriormente.

+1

¿Alguien ha intentado esto con async apagado? Supongo que esto evitaría que el navegador se descargue hasta que se devuelva la solicitud. –

+3

Eso es correcto. Con la función de sincronización desactivada, el navegador esperará la respuesta del servidor antes de descargar la página. Esto ayuda con los errores de Chrome, donde Chrome es muy poco confiable cuando se trata de descargar eventos y operaciones de sincronización. Esto también arreglará la conexión IE que acapara lo que describí anteriormente. Pero será visible por el usuario. –

+2

Vale la pena vigilar la nueva API de Beacon con 'Navigator.sendBeacon' que permitirá una mejor manera de emitir de forma confiable una solicitud asíncrona a nuestro servidor en la descarga: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon – Wildhoney

1

Tendrá que hacer sus propias pruebas para saber si su escenario particular funciona o no con el tiempo que tiene en unload, pero hacer la solicitud AJAX es bastante rápido, ya que AJAX es asincrónico. ¡Simplemente envía la solicitud y listo! (Tal vez tendrá que borrar el objeto de solicitud que acaba de crear, sin embargo)

Si desea verificar que la solicitud AJAX lo hizo, entonces tendría que preocuparse más/utilice la opción async:false (como this discussion indica). Pero, solo enviar es una operación rápida de boom-y-ya está hecho.

+1

Bueno, no voy a llamarlo fiable si no se puede alcanzar el servidor, ¿verdad? ;) –

+1

Cierto, pero pensé que se refería a confiable, ya que el navegador realmente enviará la solicitud. – palswim

3

Tenemos un caso en el que necesitábamos eso. Es una página de informe que necesita memoria seria en el servidor, por lo que queríamos liberarla tan pronto como salieran de la página. Creamos un conjunto de marcos y agregamos el controlador de descarga allí. La forma más confiable era establecer el src de una imagen en el script de liberación. De hecho, utilizamos tanto la descarga como antes de descargar para compatibilidad con navegadores cruzados. No funcionó en las colecciones nocturnas de los kits web, pero la administración estuvo de acuerdo con eso.

Sin embargo, esa no fue mi solución propuesta. Usaría un enfoque de latido que implica más trabajo pero es mucho más sólido.

Su página debe enviar solicitudes de latidos periódicos. Cada solicitud establece el último latido de una página. Luego necesita un hilo que se ejecuta en el servidor y borra la memoria si el último latido fue demasiado largo.

Esto no resuelve el problema de dejar la página abierta durante mucho tiempo. Para eso necesita algún control para la actividad del usuario y abandonar esa página después de un período de inactividad (asegúrese de confirmar con el usuario)

+0

¿Realmente * necesitas el 'frameset', la imagen y el método de script de liberación? Parece bastante hackish ... ¿O fue mucho más confiable en comparación con el uso de los dos eventos de "descarga"? –

+0

Necesitábamos el conjunto de marcos porque había navegación dentro de la página, solo queríamos enviar la solicitud de "memoria libre" cuando navegamos fuera del conjunto de páginas. El método de imagen/dos descargas fue la forma en que logramos ejecutarlo de manera más confiable en todos los navegadores y sistemas operativos. –

12

Ha intentado utilizar

var i = new Image(1,1); 
i.src='http://...' 

Y acaban de volver alguna imagen vacío desde el servidor. Creo que debería ser confiable, el script bloqueará. Por cierto: es agradable agregar la fecha y hora para evitar el almacenamiento en caché.

+0

Encontré que las llamadas AJAX en la función de evento onload no funcionaban, pero este método sí. Cabe señalar que el código de la función no se detiene o bloquea la descarga de la página, el código puede ejecutarse después de que la página se haya descargado. – nuander

-2

Tenía un caso en el que solo tenía que notificar al servidor sobre la descarga y no me interesaba la respuesta.

Si esa es su caso, puede ignore_user_abort y entonces usted sabe que va a suceder "fiable"

Cuestiones relacionadas