Long Polling mit jQuery und PHP: Tutorial.
22. Oktober 2013 · Kategorien: Internet, PHP, Webentwicklung

Dieses Tutorial wird Dir erklären, wie Du Long Polling (= Comet) mit Hilfe von jQuery und PHP umsetzt. Die Implementierung ist zwar relativ einfach, allerdings gibt es doch einiges zu beachten.
Was ist Long Polling aka Comet?
Nehmen wir als klassisches Beispiel eine Chatsoftware, die wir allein mit PHP und JavaScript umgesetzt möchten.
Wenn Person A mit Person B chattet, muss die Chatsoftware dafür sorgen, dass B möglichst schnell eine Nachricht erhält, sobald A eine Nachricht abgesendet hat.
Eine nahe liegende Lösung wäre es, mit Hilfe von window.setTimeout alle paar Sekunden einen neuen Request abzusenden, der überprüft, ob eine neue Nachricht in der Datenbank liegt.
function checkForNewMessages() { $.ajax({ type: "POST", url: "chat.php" }).done(function(result) { if(result.messageReceived) { ... Nachricht wurde empfangen ... } }); window.setTimeout(function() { checkForNewmessages(); }, 10000); }; checkForNewMessages();
Das hat zwei starke Nachteile:
Zum einen erhält der Benutzer die Nachricht nur verzögert. Würden wir also das Zeitintervall für window.setTimeout auf 10 Sekunden stellen (was schon sehr kurz ist), erhält Person B im schlimmsten Fall erst 10 Sekunden zu spät die Nachricht.
Ein weiterer Nachteil ist, dass mit jedem Request eine Verbindung zum Server aufgebaut werden muss. Das ist sehr teuer, da jedes Mal diverse Vorgänge stattfinden müssen, bevor die eigentliche Überprüfung durchgeführt werden kann.
Zum Beispiel muss jedes Mal überprüft werden, ob der Benutzer eingeloggt ist. Wenn ein Framework benutzt wird, werden jedes Mal alle benötigten Schritte zur Initialisierung durchgeführt.
Mit Hilfe von Comet bzw. Long Polling ist es möglich, diese Nachteile allein mit jQuery und PHP zu umgehen.
Wie funktioniert Long Polling?
Long Polling bedeutet, dass eine Verbindung zum Server aufrecht erhalten wird. Und zwar so lange, bis das gewünschte Ereignis – in unserem Beispiel das Empfangen einer Chatnachricht – in Kraft tritt.
Solange das nicht passiert ist, bleibt die Verbindung bestehen. Es findet also im Normalfall nur ein Request pro Nachricht statt.
Der jQuery-Code sieht nun so aus:
function checkForNewMessages() { $.ajax({ type: "GET", url: "chat.php", timeout: 300000 }).done(function(result) { if(result.messageReceived) { ... Nachricht wurde empfangen ... } checkForNewMessages(); }); }; checkForNewMessages();
Viel hat sich nicht geändert. Der Unterschied ist, dass wir die Funktion checkForNewMessages nun erst wieder aufrufen, wenn wir eine Antwort vom Server erhalten haben. Da wir nicht mehr alle paar Sekunden eine neue Abfrage senden müssen, brauchen wir auch keinen Gebrauch mehr von window.setTimeout zu machen.
Wir geben noch einmal explizit das Timeout sehr hoch an (im Beispiel 5 Minuten), sodass das Request nicht vorzeitig abgebrochen wird.
Der PHP-Code, im Beispiel also die chat.php sieht so aus:
if(session_id()) { session_close(); } $message = null; while(!$message) { sleep(5); $message = liesNeueNachichtAusDatenbank(); }
Solange keine Nachricht empfangen wurde, ist $message = null. Das heißt, die while-Schleife wird dann wieder durchlaufen. Wir nutzen sleep(5), um zwischen jeder Datenbankabfrage 5 Sekunden zu warten. Das hat zwar zur Folge, dass der Benutzer im schlimmsten Fall 5 Sekunden auf eine neue Nachricht warten müsste, allerdings können wir dieses Intervall relativ niedrig ansetzen. Eine gut optimierte Datenbankabfrage (mit Indezes) kostet nämlich nicht viel.
Gegebenenfalls ist es wichtig, dass wir die Session schließen!
Es ist nämlich so, dass ein Webserver, beispielsweise Apache, weitere Requests sperrt, während ein Request auf die Session zugreift. Auf diese Weise werden Race Conditions vermieden.
Das heißt, für den Benutzer würde keine weitere Seite laden (zum Beispiel in einem neuen Tab), bevor das Long Polling Request nicht abgeschlossen wurde.
Long Polling Requests debuggen
Um Long Polling Requests zu debuggen, empfehle ich euch Firebug für Firefox oder Chrome. In den Webentwicklertools (F12 unter Windows/Linux bzw. CMD + alt + I auf dem Mac). Dort könnt ihr im Netzwerk-Tab in den XHR-Requests sämtliche Requests einsehen, die von einer Webseite ausgehen. Long Polling Requests stehen für gewöhnlich lange Zeit auf “Pending”. Das bedeutet, der Browser wartet noch auf eine Antwort.
Bitte schreibe ein Kommentar, wenn Du etwas nicht verstehst oder Anmerkungen hast. Ich helfe gerne.
Autor: Christian Kilb | Kategorien: Internet, PHP, Webentwicklung
Was würdest du machen wenn der User während des “Long Polling” die Seite neu lädt?