Es ist einfacher, als ich anfangs dachte. Im Grunde haben Sie eine Seite, die nichts tut, bis die Daten, die Sie senden möchten, verfügbar sind (z. B. eine neue Nachricht eintrifft).
Hier ist ein sehr einfaches Beispiel, das nach 2-10 Sekunden eine einfache Zeichenkette sendet. 1 zu 3 Chance, einen Fehler 404 zurückzugeben (um die Fehlerbehandlung im kommenden Javascript-Beispiel zu zeigen)
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));
?>
Hinweis: Bei einer echten Website wird die Ausführung auf einem normalen Webserver wie Apache schnell alle "Worker-Threads" blockieren und ihn unfähig machen, auf andere Anfragen zu reagieren. Es gibt Möglichkeiten, dies zu umgehen, aber es wird empfohlen, einen "Long-Poll-Server" in etwas wie Python zu schreiben verdrillt die nicht auf einen Thread pro Anfrage angewiesen ist. cometD ist ein beliebtes Programm (das in mehreren Sprachen verfügbar ist), und Tornado ist ein neues Framework, das speziell für solche Aufgaben entwickelt wurde (es wurde für den Long-Polling-Code von FriendFeed entwickelt)... aber als einfaches Beispiel ist Apache mehr als ausreichend! Dieses Skript könnte leicht in jeder beliebigen Sprache geschrieben werden (ich habe mich für Apache/PHP entschieden, da sie sehr weit verbreitet sind und ich sie zufällig lokal ausgeführt habe)
Dann fordern Sie in Javascript die oben genannte Datei an ( msg_srv.php
), und warten Sie auf eine Antwort. Wenn Sie eine erhalten, verarbeiten Sie die Daten. Dann fordern Sie die Datei an, warten wieder, verarbeiten die Daten (und wiederholen)
Im Folgenden finden Sie ein Beispiel für eine solche Seite Wenn die Seite geladen wird, sendet sie die erste Anfrage für die msgsrv.php
Datei. Wenn dies gelingt, wird die Nachricht an die Datei #messages
div, dann rufen wir nach 1 Sekunde erneut die Funktion waitForMsg auf, die das Warten auslöst.
Die 1 Sekunde setTimeout()
ein wirklich einfacher Ratenbegrenzer ist, funktioniert er auch ohne dies, aber wenn msgsrv.php
immer sofort zurückkehrt (z. B. mit einem Syntaxfehler), überfluten Sie den Browser und er kann schnell einfrieren. Besser wäre es, zu prüfen, ob die Datei eine gültige JSON-Antwort enthält, und/oder eine laufende Gesamtzahl von Anfragen pro Minute/Sekunde zu erfassen und entsprechend zu pausieren.
Wenn die Seite fehlerhaft ist, wird der Fehler an die #messages
div, wartet 15 Sekunden und versucht es dann erneut (genauso wie wir nach jeder Nachricht 1 Sekunde warten)
Das Schöne an diesem Ansatz ist, dass er sehr widerstandsfähig ist. Wenn die Internetverbindung des Clients abbricht, wird eine Zeitüberschreitung ausgelöst, dann wird versucht, die Verbindung wiederherzustellen - dies ist inhärent in der Art und Weise, wie Long Polling funktioniert, es ist keine komplizierte Fehlerbehandlung erforderlich
Wie auch immer, die long_poller.htm
Code, der das jQuery-Framework verwendet:
<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>