2010-06-29 30 views
31

Básicamente, una vez que un usuario deja una página web en mi aplicación, necesito llamar a una secuencia de comandos PHP con AJAX, que insertará un tiempo pasado en la página web a la base de datos y luego abandonar la página.

Es importante esperar a que finalice la solicitud AJAX porque las páginas web de mi aplicación no son accesibles para los usuarios a menos que hayan pasado cierto tiempo en una página anterior (digamos dos minutos).

Aquí está mi código jQuery:

$(document).ready(function() { 

    var teid = TEID; 
    var startTime = new Date().getTime(); 

    $(window).unload(function() { 
     var timeSpentMilliseconds = new Date().getTime() - startTime; 
     var t = timeSpentMilliseconds/1000/60; 

     $.ajax({ 
      type: 'POST', 
      url: '/clientarea/utils/record-time', 
      data: 'teid=' + teid + '&t=' + t 
     }); 
    }); 

}); 

¿Cómo debería cambiarlo por lo que esperará a que la petición AJAX para terminar antes de salir de la página web?

EDIT:

O podría ser mejor (más fácil) para dejar que la petición AJAX se repetirá cada minuto más o menos. ¿Es eso posible?

Respuesta

30

Bien, puede configurar async: false en su llamada AJAX para que el navegador espere a que la solicitud termine antes de hacer cualquier otra cosa, pero tenga en cuenta que esto "colgará" el navegador mientras dure la solicitud.

$.ajax({ 
    type: 'POST', 
    async: false, 
    url: '/clientarea/utils/record-time', 
    data: 'teid=' + teid + '&t=' + t 
}); 

Desde el manual:

Por defecto, todas las peticiones son enviadas asincrónico (es decir, esto se establece en verdadero por defecto). Si necesita solicitudes sincrónicas, establezca esta opción en falso. Solicitudes entre dominios y tipo de datos: las solicitudes "jsonp" no son compatibles con la operación síncrona. Tenga en cuenta que las solicitudes sincrónicas pueden bloquear temporalmente el navegador, deshabilitando cualquier acción mientras la solicitud está activa.

+0

Hmm. Gracias. He actualizado mi pregunta. Sería más fácil simplemente dejar que la solicitud AJX repita cada digamos un minuto. ¿Como podría hacerlo? –

+12

Recomiendo evitar eso, ** especialmente ** en 'descargar'. – jAndy

+0

He encontrado que siempre hay una mejor solución que hacer 'async: false', independientemente del problema. –

4

para mí, el suyo no es una buena idea para que el navegador espera antes de cerrar ...
simplemente porque lo que si realmente quiero cerrarla? ...

si una página se molestó un usuario, no es bueno ...

mi sugerencia es, en la página, espere 2 minutos (si son 2 minutos los requisitos), luego envíe un ajax que el usuario ha hecho sus 2 minutos ...

puede verificarlo en el lado del servidor si uno tiene sus 2 minutos o no ...

0

El método jQuery.ajax() tiene la opción async. Si lo configura en false, la llamada se bloqueará hasta que vuelva la respuesta (o se agotó el tiempo de espera). Estoy bastante seguro de que, al llamar esto, el navegador se usará en el controlador de descarga.

Nota al margen: No puede confiar en que esto funcione. Si el navegador le da al usuario la opción de cancelar los controladores de descarga (lo que algunos navegadores hacen después de un tiempo de espera), el "tiempo invertido en el sitio" nunca se actualizará. Podría agregar un temporizador al sitio, que periódicamente llama un script en el servidor y actualiza la hora. No tendrá un valor exacto, pero en su caso, esto no es necesario.

Si solo necesita saber si el usuario estuvo X segundos en la página Simplemente puede establecer un tiempo de espera en el controlador de carga (usando setTimeout(function, ms)) que hace una llamada si el usuario ha gastado el tiempo necesario. Entonces no habría necesidad de un controlador de descarga.

1

uso onbeforeunload:

$(document).ready(function(){ 
    window.onbeforeunload = function(){ 
    // $.ajax stuff here 
    return false; 
    } 
}); 

Esto por lo menos llevar al usuario una messagebox la que le pregunta si quiere cerrar la ventana/pestaña actual.

1

Creo que sería mucho mejor utilizar una técnica de sondeo como usted sugiere, aunque causará cierta carga en el servidor web.

$(document).ready(function() { 

    var teid = TEID; 
    var startTime = new Date().getTime(); 

    var ajaxFunc = function() { 
     var timeSpentMilliseconds = new Date().getTime() - startTime; 
     var t = timeSpentMilliseconds/1000/60; 

     $.ajax({ 
      type: 'POST', 
      url: '/clientarea/utils/record-time', 
      data: 'teid=' + teid + '&t=' + t 
     }); 
    }; 

    setInterval(ajaxFunc, 60000); 

}) 

Alegrará cuando se puede usar websockets :)

+0

Gracias. ¿Pero esto solo se ejecutará una vez después de un minuto? ¿Podría ejecutarse repetidamente cada minuto (60 segundos)? –

+2

Eso es lo que hace setInterval, a diferencia de setTimeout – sje397

2

Es una mala idea para tratar de secuestrar el navegador de sus usuarios, ya que les dará una mala sensación y enviar a la basura.

Si por algún motivo no desea producir una nueva página hasta que el usuario haya dedicado un tiempo mínimo a la anterior, lo mejor es dirigir el servidor, es decir, redireccionar a la página actual hasta el momento solicitado ha pasado.

Ni siquiera necesita hacer llamadas ajax, solo almacene en la sesión la marca de tiempo de cuando se sirvió la página, y no muestre la página siguiente hasta que haya transcurrido un cierto tiempo.

Asegúrese de decirle a los usuarios que tienen que esperar que una nueva página esté lista, tal vez con una simple cuenta atrás de javascript.

Si desea que el usuario realmente tenga la página activa durante un cierto período de tiempo (es decir, no cambiar a otra pestaña/ventana esperando que transcurran los dos minutos), no puedo proponer una solución efectiva.

6

¿Qué tal establecer una cookie en el controlador de descarga? El servidor debería verlo en las solicitudes posteriores.

<script> 
    $(window).unload(function(){document.cookie='left_on='+(new Date())}) 
</script> 
7

La mejor solución es utilizar navigator.sendBeacon. Es una funcionalidad completamente nueva que se está empezando a implementar en las nuevas versiones de navegadores. La función está disponible en navegadores más nuevos que Chrome 39 y Firefox 31. No es compatible con Internet Explorer y Safari en el momento de la escritura. Para garantizar que su solicitud se envía en los navegadores que no soportan la nueva funcionalidad sin embargo, puede utilizar esta solución:

var navigator.sendBeacon = navigator.sendBeacon || function (url, data) { 
    var client = new XMLHttpRequest(); 
    client.open("POST", url, false); // third parameter indicates sync xhr 
    client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8"); 
    client.send(data); 
}; 

Espero que esto ayude!

+0

Creo que es elegante, lo usé en Electron para enviar datos cuando la aplicación está cerrada – furiel

+0

En 2018, este es el camino a seguir. – Baishu

Cuestiones relacionadas