È più semplice di quanto pensassi inizialmente .. Fondamentalmente hai una pagina che non fa nulla, fino a quando i dati che vuoi inviare non sono disponibili (diciamo, arriva un nuovo messaggio).
Ecco un esempio davvero semplice, che invia una semplice stringa dopo 2-10 secondi. 1 possibilità su 3 di restituire un errore 404 (per mostrare la gestione degli errori nel prossimo esempio di 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 sito reale, eseguirlo su un normale server Web come Apache collegherà rapidamente tutti i "thread di lavoro" e non sarà in grado di rispondere ad altre richieste. Esistono modi per aggirare questo problema, ma si consiglia di scrivere un "server di polling lungo" in qualcosa come Python's twisted , che non si basa su un thread per richiesta. cometD è popolare (disponibile in diverse lingue) e Tornado è un nuovo framework creato appositamente per tali attività (è stato creato per il codice di polling lungo di FriendFeed) ... ma come esempio semplice, Apache è più che adeguato ! Questo script potrebbe essere facilmente scritto in qualsiasi lingua (ho scelto Apache / PHP in quanto sono molto comuni e mi è capitato di eseguirli localmente)
Quindi, in Javascript, richiedi il file sopra ( msg_srv.php
) e attendi una risposta. Quando ne ottieni uno, agisci sui dati. Quindi richiedi il file e attendi di nuovo, agisci sui dati (e ripeti)
Quello che segue è un esempio di tale pagina .. Quando la pagina viene caricata, invia la richiesta iniziale per il msgsrv.php
file .. Se riesce, aggiungiamo il messaggio al #messages
div, quindi dopo 1 secondo chiamiamo di nuovo la funzione waitForMsg, che fa scattare l'attesa.
Il 1 secondo setTimeout()
è un limitatore di velocità davvero di base, funziona bene senza questo, ma se ritorna msgsrv.php
sempre all'istante (con un errore di sintassi, ad esempio) - si inonda il browser e può congelarsi rapidamente. Ciò sarebbe meglio verificare se il file contiene una risposta JSON valida e / o mantenere un totale in esecuzione di richieste al minuto / secondo e fare una pausa appropriata.
Se la pagina si guasta, aggiunge l'errore al #messages
div, attende 15 secondi e quindi riprova (identico a come aspettiamo 1 secondo dopo ogni messaggio)
La cosa bella di questo approccio è che è molto resistente. Se la connessione Internet dei client si interrompe, si verificherà il timeout, quindi prova a riconnetterti: questo è inerente alla durata del polling, non è richiesta una gestione complicata degli errori
Ad ogni modo, il long_poller.htm
codice, usando il framework 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>