Es más simple de lo que pensé inicialmente. Básicamente, tiene una página que no hace nada, hasta que los datos que desea enviar estén disponibles (por ejemplo, llega un nuevo mensaje).
Aquí hay un ejemplo realmente básico, que envía una cadena simple después de 2-10 segundos. 1 de cada 3 posibilidades de devolver un error 404 (para mostrar el manejo de errores en el próximo ejemplo de Javascript)
msgsrv.php
<?php
if(rand(1,3) == 1){
/* Fake an error */
header("HTTP/1.0 404 Not Found");
die();
}
/* Send a string after a random number of seconds (2-10) */
sleep(rand(2,10));
echo("Hi! Have a random number: " . rand(1,10));
?>
Nota: con un sitio real, ejecutar esto en un servidor web normal como Apache vinculará rápidamente todos los "subprocesos de trabajo" y dejará que no pueda responder a otras solicitudes. Hay formas de evitar esto, pero se recomienda escribir un "servidor de sondeo largo" en algo como Python torcido , que no se basa en un hilo por solicitud. cometD es popular (que está disponible en varios idiomas), y Tornado es un nuevo marco creado específicamente para tales tareas (fue construido para el código de sondeo largo de FriendFeed) ... pero como un simple ejemplo, Apache es más que adecuado ! Este script podría escribirse fácilmente en cualquier idioma (elegí Apache / PHP, ya que son muy comunes, y resultó que los ejecutaba localmente)
Luego, en Javascript, solicita el archivo anterior ( msg_srv.php
) y espera una respuesta. Cuando obtienes uno, actúas sobre los datos. Luego solicita el archivo y espera nuevamente, actúa sobre los datos (y repite)
Lo que sigue es un ejemplo de dicha página ... Cuando se carga la página, envía la solicitud inicial del msgsrv.php
archivo ... Si tiene éxito, agregamos el mensaje al #messages
div, luego de 1 segundo llamamos a la función waitForMsg nuevamente, lo que desencadena la espera.
El 1 segundo setTimeout()
es un limitador de velocidad realmente básico, funciona bien sin esto, pero si msgsrv.php
siempre regresa instantáneamente (con un error de sintaxis, por ejemplo): inunda el navegador y puede congelarse rápidamente. Será mejor que verifique si el archivo contiene una respuesta JSON válida y / o mantenga un total acumulado de solicitudes por minuto / segundo, y pause adecuadamente.
Si la página falla, agrega el error al #messages
div, espera 15 segundos y luego lo intenta nuevamente (idéntico a cómo esperamos 1 segundo después de cada mensaje)
Lo bueno de este enfoque es que es muy resistente. Si la conexión a Internet del cliente se corta, se agota el tiempo de espera, luego intenta volver a conectarse; esto es inherente a la duración del sondeo, no se requiere un manejo de errores complicado
De todos modos, el long_poller.htm
código, usando el marco jQuery:
<html>
<head>
<title>BargePoller</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css" media="screen">
body{ background:#000;color:#fff;font-size:.9em; }
.msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
.old{ background-color:#246499;}
.new{ background-color:#3B9957;}
.error{ background-color:#992E36;}
</style>
<script type="text/javascript" charset="utf-8">
function addmsg(type, msg){
/* Simple helper to add a div.
type is the name of a CSS class (old/new/error).
msg is the contents of the div */
$("#messages").append(
"<div class='msg "+ type +"'>"+ msg +"</div>"
);
}
function waitForMsg(){
/* This requests the url "msgsrv.php"
When it complete (or errors)*/
$.ajax({
type: "GET",
url: "msgsrv.php",
async: true, /* If set to non-async, browser shows page as "Loading.."*/
cache: false,
timeout:50000, /* Timeout in ms */
success: function(data){ /* called when request to barge.php completes */
addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
setTimeout(
waitForMsg, /* Request next message */
1000 /* ..after 1 seconds */
);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
addmsg("error", textStatus + " (" + errorThrown + ")");
setTimeout(
waitForMsg, /* Try again after.. */
15000); /* milliseconds (15seconds) */
}
});
};
$(document).ready(function(){
waitForMsg(); /* Start the inital request */
});
</script>
</head>
<body>
<div id="messages">
<div class="msg old">
BargePoll message requester!
</div>
</div>
</body>
</html>