WebSockets und Application Events

17. August 2017

Die klassische Kommunikation per HTTP zwischen Browser und Webserver ist recht einseitig: Der Browser sendet eine Anfrage, der Webserver beantwortet diese. Es gibt keine Möglichkeit für den Webserver von sich aus in Verbindung mit dem Browser zu treten.

Im Unterschied zu HTTP bietet WebSockets genau diese Möglichkeit: Der Webserver kann hier von sich aus Nachrichten an alle oder ausgewählte Browser senden. Eine typische Anwendung dafür ist z. B. Chat.

Womodo 7.4.4 unterstützt diese Technologie mit Hilfe von "Application Events".

Bei WebSockets wird die Kommunikation initial vom Browser aufgebaut und bleibt solange bestehen, bis der Browser geschlossen wird. Solange die Verbindung besteht, können beide Partner unabhängig voneinander Nachrichten an den jeweils anderen senden.

In womodo ist der <tml:htmlhead> Tag dafür verantwortlich, die notwendigen Scripte zum Verbindungsaufbau zu erzeugen. Womodo tut dies, sobald das aktuelle Web-Projekt ein "managed global" mit Scope "TMLPAGE" enthält, das im App-Connect Script definiert wird.

WGA.app().managedGlobal("ChatHandler", $.ChatHandler, {
scope: WGA.Scopes.TMLPAGE
})

Um die Kommunikation zu einem Browser aufzubauen werden "Application Events" verwendet (die z. B. durch Button-Klick per TML-Action gefeuert werden):

WGA.app().fireEvent("Hallo");

Für den im obigen Beispiel erzeugten Event "Hallo" wird nun ein Event-Listerer benötigt, der auf den Event reagiert. Diesen definiert man wie folgt im oben erzeugen "Golbal":

ChatHandler.prototype.hallo = function(){
// ... }.listenToAppEvents("Hallo");

Ein solcher "Listener" existiert damit für jeden verbundenen Client (Browser). Dafür sorgt der Scope WGA.Scopes.TMLPAGE in der Global-Definition.

Der Event-Handler wird mit einem Parameter $websocket aufgerufen, über den man per $websocket.firePortletEvent() beliebige Daten an den Client (den Browser) senden kann:

ChatHandler.prototype.hallo = function($websocket){
$websocket.firePortletEvent("message-from-webserver", {
msg: "Meine Nachricht ..."
});
}.listenToAppEvents("Hallo");

In obigen Beispiel werden die Daten an alle verbundenen Clients gesendet. Will man gezielt einzelne Clients ansprechen, kann man dies z. B. über Event-Parameter steuern:

WGA.app().fireEvent("Hallo", {
to: "Wolfgang Schmidetzki",
msg: "Hallo ws"
});

Angepaßter Event-Handler:

ChatHandler.prototype.hallo = function($websocket, $event){
if($event.params.to != meta("db", "username"))
return; // nicht für mich
$websocket.firePortletEvent("message-from-webserver", {
msg: $event.params.msg
});
}.listenToAppEvents("Hallo");

Der Browser muß dazu auf Portlet-Events horchen. Dies geschieht entweder, wenn ein (Ajax-)Portlet gerendert wurde, das auf diesen Event per <tml:eventscript> horcht oder indem explizit per JavaScript ein Event-Handler implementiert wird:

<script>
WGA.event.addListener("*", "message-from-webserver", function(e){
console.log("message received", e.params.msg);
})
</script>

Web-Chat

Mit Hilfe der hier beschrieben Techniken kann z. B. eine Web-Chat Anwendung implementiert werden, die es einem Website-Betreiber ermöglicht, direkt in Kontakt mit einem Website-Besucher zu treten, um z. B. Fragen persönlich zu beantworten.

womodo websockets