C'est plus simple que je ne le pensais au départ En gros, vous avez une page qui ne fait rien, jusqu'à ce que les données que vous voulez envoyer soient disponibles (disons, un nouveau message arrive).
Voici un exemple vraiment basique, qui envoie une simple chaîne de caractères après 2 à 10 secondes. 1 chance sur 3 de renvoyer 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));
?>
Note : Avec un site réel, l'exécution de cette opération sur un serveur web ordinaire comme Apache va rapidement bloquer tous les "fils de travail" et le laisser incapable de répondre à d'autres demandes Il existe des moyens de contourner ce problème, mais il est recommandé d'écrire un "serveur de sondage long" dans un langage comme Python. tordu qui ne repose pas sur un thread par requête. cometD est populaire (il est disponible en plusieurs langues), et Tornade est un nouveau framework fait spécifiquement pour de telles tâches (il a été construit pour le code de sondage long de FriendFeed)... mais comme exemple simple, Apache est plus qu'adéquat ! Ce script pourrait facilement être écrit dans n'importe quel langage (j'ai choisi Apache/PHP car ils sont très courants, et il se trouve que je les utilisais localement).
Ensuite, en Javascript, vous demandez le fichier ci-dessus ( msg_srv.php
), et attendez une réponse. Lorsque vous en recevez une, vous agissez sur les données. Ensuite, vous demandez le fichier, attendez à nouveau, traitez 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 requête initiale pour le fichier msgsrv.php
fichier.. S'il réussit, nous ajoutons le message au fichier #messages
puis, après une seconde, nous appelons à nouveau la fonction waitForMsg, ce qui déclenche l'attente.
La 1 seconde setTimeout()
est un limiteur de débit très basique, il fonctionne bien sans cela, mais si msgsrv.php
toujours retourne instantanément (avec une erreur de syntaxe, par exemple) - vous inondez le navigateur et il peut rapidement se figer. Il serait préférable de vérifier si le fichier contient une réponse JSON valide, et/ou de garder un total de requêtes par minute/seconde, et de mettre en pause de manière appropriée.
Si la page est erronée, elle ajoute l'erreur à l'élément #messages
div, attend 15 secondes puis réessaie (identique à la façon dont nous attendons 1 seconde après chaque message).
L'avantage de cette approche est qu'elle est très résistante. Si la connexion internet du client est interrompue, il y aura un délai d'attente, puis il essaiera de se reconnecter - c'est inhérent au fonctionnement de l'interrogation à long terme, aucune gestion d'erreur compliquée n'est nécessaire.
Quoi qu'il en soit, le long_poller.htm
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>