C'est plus simple que je ne le pensais au départ. Fondamentalement, vous avez une page qui ne fait rien, jusqu'à ce que les données que vous souhaitez envoyer soient disponibles (par exemple, un nouveau message arrive).
Voici un exemple vraiment basique, qui envoie une chaîne simple au bout de 2 à 10 secondes. 1 chance sur 3 de retourner une erreur 404 (pour montrer la gestion des erreurs dans l'exemple Javascript à venir)
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));
?>
Remarque: Avec un site réel, l'exécuter sur un serveur Web ordinaire comme Apache bloquera rapidement tous les «threads de travail» et le laissera incapable de répondre à d'autres demandes. Il existe des moyens de contourner cela, mais il est recommandé d'écrire un "serveur à interrogation longue" dans quelque chose comme Python tordu , qui ne repose pas sur un thread par demande. cometD est populaire (disponible en plusieurs langues), et Tornado est un nouveau framework spécialement conçu pour ces tâches (il a été conçu pour le code de polling long de FriendFeed) ... mais à titre d'exemple simple, Apache est plus que suffisant ! Ce script pourrait facilement être écrit dans n'importe quelle langue (j'ai choisi Apache / PHP car ils sont très courants et je les ai exécutés localement)
Ensuite, en Javascript, vous demandez le fichier ci-dessus ( msg_srv.php
) et attendez une réponse. Lorsque vous en obtenez un, vous agissez sur les données. Ensuite, vous demandez le fichier et attendez à nouveau, agissez sur les données (et répétez)
Ce qui suit est un exemple d'une telle page. Lorsque la page est chargée, elle envoie la demande initiale pour le msgsrv.php
fichier. Si elle réussit, nous ajoutons le message à la #messages
div, puis après 1 seconde nous appelons à nouveau la fonction waitForMsg, ce qui déclenche l'attente.
La 1 seconde setTimeout()
est un limiteur de débit vraiment basique, cela fonctionne très bien sans cela, mais s'il revient msgsrv.php
toujours instantanément (avec une erreur de syntaxe, par exemple) - vous inondez le navigateur et il peut rapidement geler. Il serait préférable de vérifier si le fichier contient une réponse JSON valide et / ou de conserver un total cumulé de requêtes par minute / seconde, et de faire une pause appropriée.
Si la page fait une erreur, il ajoute l'erreur à la #messages
div, attend 15 secondes puis réessaye (identique à la façon dont nous attendons 1 seconde après chaque message)
La bonne chose à propos de cette approche est qu'elle est très résistante. Si la connexion Internet du client meurt, elle expirera, puis essayez de vous reconnecter - cela est inhérent à la durée de l'interrogation, aucune gestion d'erreur complexe n'est requise
Quoi qu'il en soit, le long_poller.htm
code, en utilisant le 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>