Weder HTML noch HTTP wurden für dynamische Webanwendungen erstellt. Wir setzen im Wesentlichen auf Hacks, zusätzlich zu Hacks, um unseren Apps eine ansprechende Benutzeroberfläche zu bieten. AngularJS hebt einige Einschränkungen aus HTML auf, sodass Benutzeroberflächencode einfacher erstellt und verwaltet werden kann. Socket.IO hingegen hilft uns beim Senden von Daten vom Server, nicht nur, wenn der Client dies anfordert, sondern auch, wenn der Server dies erfordert. In diesem Artikel werde ich Ihnen zeigen, wie Sie diese beiden kombinieren können, um die Reaktionsfähigkeit Ihrer einseitigen Apps zu verbessern.
Im ersten Teil dieses Tutorials erstellen wir einen wiederverwendbaren AngularJS-Service für Socket.IO. Deswegen wiederverwendbar Teilweise wird dies ein wenig schwieriger sein als nur die Verwendung module.service ()
oder module.factory ()
. Bei diesen beiden Funktionen handelt es sich lediglich um syntaktischen Zucker neben dem eher niedrigen Niveau module.provider ()
Methode, die wir verwenden werden, um einige Konfigurationsoptionen bereitzustellen. Wenn Sie AngularJS noch nie verwendet haben, rate ich Ihnen dringend, mindestens das offizielle Tutorial und einige der Tutorials zu Tuts hier zu befolgen+.
Bevor wir anfangen, unser AngularJS-Modul zu schreiben, benötigen wir ein einfaches Back-End zum Testen. Wenn Sie bereits mit Socket.IO vertraut sind, können Sie einfach bis zum Ende dieses Abschnitts scrollen, die Back-End-Quelle kopieren und mit der nächsten fortfahren, falls nicht - lesen Sie weiter.
Wir werden nur brauchen socket.io
. Sie können es entweder direkt mit installieren npm
Befehl wie folgt:
npm install socket.io
Oder erstellen Sie eine package.json
Datei, setzen Sie diese Zeile in die Abhängigkeiten
Sektion:
"socket.io": "0.9.x"
Und das ausführen npm installieren
Befehl.
Da wir kein kompliziertes Web-Framework wie Express benötigen, können wir den Server mit Socket.IO erstellen:
var io = erfordern ('socket.io') (8080);
Das ist alles, was Sie brauchen, um den Socket.IO-Server einzurichten. Wenn Sie Ihre App starten, sollten Sie eine ähnliche Ausgabe in der Konsole sehen:
Und Sie sollten auf das zugreifen können socket.io.js
Datei in Ihrem Browser unter http: // localhost: 8080 / socket.io / socket.io.js:
Wir werden alle eingehenden Verbindungen in der Verbindung
Ereignis-Listener der Steckdosen
Objekt:
io.sockets.on ('Verbindung', Funktion (Socket) );
Das Steckdose
Das an den Rückruf übergebene Attribut ist der Client, der eine Verbindung hergestellt hat, und wir können Ereignisse darauf überwachen.
Jetzt fügen wir im obigen Rückruf einen grundlegenden Ereignis-Listener hinzu. Es sendet die empfangenen Daten mit dem Client an den Client zurück socket.emit ()
Methode:
socket.on ('echo', Funktion (Daten) socket.emit ('echo', data););
Echo
ist der benutzerdefinierte Ereignisname, den wir später verwenden werden.
Wir werden auch Bestätigungen in unserer Bibliothek verwenden. Mit dieser Funktion können Sie eine Funktion als dritten Parameter des übergeben socket.emit ()
Methode. Diese Funktion kann auf dem Server aufgerufen werden, um Daten an den Client zurückzusenden:
socket.on ('echo-ack', Funktion (Daten, Rückruf) Rückruf (Daten););
Auf diese Weise können Sie auf den Client antworten, ohne dass er auf Ereignisse warten muss (was nützlich ist, wenn Sie nur einige Daten vom Server anfordern möchten)..
Nun ist unser Test-Backend abgeschlossen. Der Code sollte so aussehen (Dies ist der Code, den Sie kopieren sollten, wenn Sie diesen Abschnitt weglassen):
var io = erfordern ('socket.io') (8080); io.sockets.on ('Verbindung', Funktion (Socket) Socket.on ('Echo', Funktion (Daten) Socket.emit ('Echo', Daten);); Socket.on ('Echo-ack ', Funktion (Daten, Rückruf) Rückruf (Daten);););
Sie sollten jetzt die App ausführen und laufen lassen, bevor Sie mit dem Rest des Lernprogramms fortfahren.
Natürlich benötigen wir etwas HTML, um unsere Bibliothek zu testen. Wir müssen AngularJS einschließen, socket.io.js
von unserem Backend, unserem Winkelsockel.js
Bibliothek und einen grundlegenden AngularJS-Controller, um einige Tests auszuführen. Der Controller wird im eingeblendet des Dokuments, um den Workflow zu vereinfachen:
Das ist alles, was wir jetzt brauchen, wir werden später auf das leere Skript-Tag zurückkommen, da wir die Bibliothek noch nicht haben.
In diesem Abschnitt erstellen wir die Winkelsockel.js
Bibliothek. Der gesamte Code muss in diese Datei eingefügt werden.
Beginnen wir mit der Erstellung des Moduls für unsere Bibliothek:
var module = angle.module ('socket.io', []);
Wir haben keine Abhängigkeiten, also das Array im zweiten Argument von angle.module ()
ist leer, aber nicht vollständig entfernt, sonst erhalten Sie eine $ Injektor: nomod
Error. Dies geschieht aufgrund der Ein-Argument-Form von angle.module ()
Ruft einen Verweis auf das bereits vorhandene Modul ab, anstatt ein neues zu erstellen.
Anbieter sind eine der Möglichkeiten, AngularJS-Dienste zu erstellen. Die Syntax ist einfach: Das erste Argument ist der Name des Dienstes (nicht der Name des Anbieters!) Und das zweite Argument ist die Konstruktorfunktion für den Anbieter:
module.provider ('$ socket', $ socketProvider () );
Um die Bibliothek wieder verwendbar zu machen, müssen wir Änderungen in der Konfiguration von Socket.IO zulassen. Zunächst definieren wir zwei Variablen, die die URL für die Verbindung und das Konfigurationsobjekt enthalten (der Code in diesem Schritt geht an das $ socketProvider ()
Funktion):
var ioUrl = "; var ioConfig = ;
Nun, da diese Variablen außerhalb von nicht verfügbar sind $ socketProvider ()
Funktion (sie sind irgendwie Privatgelände), müssen wir Methoden (Setter) erstellen, um sie zu ändern. Wir könnten sie natürlich auch machen Öffentlichkeit so was:
this.ioUrl = "; this.ioConfig = ;
Aber:
Function.bind ()
später auf den entsprechenden Kontext für zugreifen diese
falsch
als die 'Verbindungs Timeout'
MöglichkeitEine vollständige Liste der Optionen für den Socket.IO-Client finden Sie im GitHub-Wiki. Wir erstellen für jeden einen Setter und einen für die URL. Alle Methoden sehen ähnlich aus, daher werde ich den Code für eine davon erläutern und den Rest unten angeben.
Definieren wir die erste Methode:
this.setConnectionUrl = Funktion setConnectionUrl (URL)
Es sollte den Typ des übergebenen Parameters überprüfen:
if (typeof url == 'string')
Wenn dies die erwartete ist, setzen Sie die Option:
ioUrl = URL;
Wenn nicht, sollte es werfen TypeError
:
else throw new TypeError ('url muss vom Typ string sein'); ;
Für den Rest können wir eine Hilfsfunktion erstellen, um es trocken zu halten:
function setOption (name, value, type) if (typeof value! = type) throw new TypeError ("'" + name + "' muss vom Typ '" + type + "'" sein); ioConfig [Name] = Wert;
Es wirft einfach TypeError
Wenn der Typ falsch ist, wird sonst der Wert festgelegt. Hier ist der Code für die restlichen Optionen:
this.setResource = Funktion setResource (value) setOption ('resource', value, 'string'); ; this.setConnectTimeout = Funktion setConnectTimeout (value) setOption ('Verbindungszeitlimit', Wert, 'Nummer'); ; this.setTryMultipleTransports = Funktion setTryMultipleTransports (value) setOption ('versuche mehrere Transporte', value, 'boolean'); ; this.setReconnect = Funktion setReconnect (value) setOption ('reconnect', value, 'boolean'); ; this.setReconnectionDelay = Funktion setReconnectionDelay (value) setOption ('Wiederherstellungsverzögerung', value, 'number'); ; this.setReconnectionLimit = Funktion setReconnectionLimit (value) setOption ('Wiederverbindungslimit', Wert, 'Nummer'); ; this.setMaxReconnectionAttetimes = Funktion setMaxReconnectionAttempt (value) setOption ('Versuche der max. Wiederverbindung', Wert, 'Nummer'); ; this.setSyncDisconnectOnUnload = Funktion setSyncDisconnectOnUnload (value) setOption ('sync disconnect on unload'), value, 'boolean'); ; this.setAutoConnect = Funktion setAutoConnect (value) setOption ('auto connect', value, 'boolean'); ; this.setFlashPolicyPort = Funktion setFlashPolicyPort (value) setOption ('flash policy port', value, 'number'); this.setForceNewConnection = Funktion setForceNewConnection (value) setOption ('neue Verbindung erzwingen', value, 'boolean'); ;
Sie könnten es durch ein einzelnes ersetzen setOption ()
Methode, aber es scheint einfacher zu sein, den Namen der Option im Kamelfall einzugeben, anstatt ihn als Zeichenfolge mit Leerzeichen zu übergeben.
Diese Funktion erstellt das Serviceobjekt, das wir später verwenden können (z. B. in Controllern). Zuerst rufen wir die an io ()
Funktion zum Verbinden mit dem Socket.IO-Server:
this. $ get = Funktion $ socketFactory ($ rootScope) var socket = io (ioUrl, ioConfig);
Beachten Sie, dass wir die Funktion dem zuweisen $ bekommen
Vom Provider erstellte Eigenschaft des Objekts. Dies ist wichtig, da AngularJS diese Eigenschaft zum Aufruf verwendet. Wir setzen auch $ rootScope
als dessen Parameter. An diesem Punkt können wir die Abhängigkeitseingabe von AngularJS verwenden, um auf andere Dienste zuzugreifen. Wir werden es verwenden, um Änderungen an beliebigen Modellen in Socket.IO-Callbacks zu verbreiten.
Nun muss die Funktion ein Objekt zurückgeben:
Rückkehr ; ;
Wir werden alle Methoden für den Dienst darin einsetzen.
auf()
MethodeDiese Methode hängt einen Ereignis-Listener an das Socket-Objekt an, sodass wir alle vom Server gesendeten Daten verwenden können:
ein: Funktion ein (Ereignis, Rückruf)
Wir werden Socket.IOs verwenden socket.on ()
um unseren Rückruf anzuhängen und ihn in AngularJS zu nennen $ scope. $ apply ()
Methode. Dies ist sehr wichtig, da Modelle nur in ihr modifiziert werden können:
socket.on (event, function ()
Zuerst müssen wir die Argumente in eine temporäre Variable kopieren, damit wir sie später verwenden können. Argumente sind natürlich alles, was der Server an uns gesendet hat:
var args = Argumente;
Als nächstes können wir unseren Rückruf mit aufrufen Function.apply ()
Argumente übergeben:
$ rootScope. $ apply (function () callback.apply (socket, args);); ); ,
Wann Steckdose
Der Ereignis-Emitter ruft die von ihm verwendete Listener-Funktion auf $ rootScope. $ apply ()
den Rückruf, der als zweites Argument bereitgestellt wird, an die .auf()
Methode. Auf diese Weise können Sie Ihre Ereignis-Listener wie für jede andere App mit Socket.IO schreiben, aber Sie können die Modelle von AngularJS darin modifizieren.
aus()
MethodeDiese Methode entfernt einen oder alle Ereignis-Listener für ein bestimmtes Ereignis. Dies hilft Ihnen, Speicherverluste und unerwartetes Verhalten zu vermeiden. Stellen Sie sich vor, Sie verwenden ngRoute
und Sie hängen in jedem Controller nur wenige Zuhörer an. Wenn der Benutzer zu einer anderen Ansicht navigiert, wird Ihr Controller zerstört, der Ereignis-Listener bleibt jedoch verbunden. Nach ein paar Navigationen haben wir ein Gedächtnisleck.
aus: Funktion aus (Ereignis, Rückruf)
Wir müssen nur prüfen, ob die Ruf zurück
wurde bereitgestellt und angerufen socket.removeListener ()
oder socket.removeAllListeners ()
:
if (typeof callback == 'function') socket.removeListener (event, callback); else socket.removeAllListeners (Ereignis); ,
emittieren()
MethodeDies ist die letzte Methode, die wir brauchen. Wie der Name vermuten lässt, sendet diese Methode Daten an den Server:
emit: Funktion emit (Ereignis, Daten, Rückruf)
Da Socket.IO Bestätigungen unterstützt, prüfen wir, ob Ruf zurück
wurde bereitgestellt. Wenn ja, verwenden wir dasselbe Muster wie im auf()
Rückrufmethode innerhalb von $ scope. $ apply ()
:
if (typeof callback == 'function') socket.emit (event, data, function () var args = Argumente; $ rootScope. $ apply (function () callback.apply (socket, args);); );
Wenn es keine gibt Ruf zurück
Wir können einfach anrufen socket.emit ()
:
else socket.emit (Ereignis, Daten);
Um die Bibliothek zu testen, erstellen wir ein einfaches Formular, das einige Daten an den Server sendet und die Antwort anzeigt. Der gesamte JavaScript-Code in diesem Abschnitt sollte in die >