Client: Implement event system (#4)
This commit is contained in:
parent
36ba716ad8
commit
ceca822f97
|
|
@ -12,6 +12,7 @@
|
||||||
<h1>InstantChat</h1>
|
<h1>InstantChat</h1>
|
||||||
|
|
||||||
<script src="js/settings.js"></script>
|
<script src="js/settings.js"></script>
|
||||||
|
<script src="js/events.js"></script>
|
||||||
<script src="js/client.js"></script>
|
<script src="js/client.js"></script>
|
||||||
<script src="js/ui.js"></script>
|
<script src="js/ui.js"></script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,18 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
class Client {
|
/**
|
||||||
|
* Client class that implements the InstantChat protocol using WebSockets.
|
||||||
|
*
|
||||||
|
* Dispatches the following events which can be subscribed/unsubscribed using .on() and .off():
|
||||||
|
* - initialized: Connection to server has been established and initialized, ready to send messages.
|
||||||
|
* - disconnected: Connection has been closed.
|
||||||
|
* - connectionError: Some connection error occurred.
|
||||||
|
* - receivedMessage: Chat message has been received. Data: object {from: 'username', text: 'text'}
|
||||||
|
*/
|
||||||
|
class Client extends EventDispatcher {
|
||||||
constructor(wsUri) {
|
constructor(wsUri) {
|
||||||
|
super();
|
||||||
|
|
||||||
this.wsUri = wsUri;
|
this.wsUri = wsUri;
|
||||||
|
|
||||||
// Create WebSocket and set internal callbacks
|
// Create WebSocket and set internal callbacks
|
||||||
|
|
@ -16,17 +27,17 @@ class Client {
|
||||||
// Internal WebSocket event handlers
|
// Internal WebSocket event handlers
|
||||||
_onSocketOpen(evt) {
|
_onSocketOpen(evt) {
|
||||||
console.log("Connected to " + this.wsUri);
|
console.log("Connected to " + this.wsUri);
|
||||||
|
|
||||||
// Send init command containing chat ID and nickname
|
|
||||||
this.sendInit();
|
this.sendInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSocketClose(evt) {
|
_onSocketClose(evt) {
|
||||||
console.log("Connection closed (code " + evt.code + ").");
|
console.log("Connection closed (code " + evt.code + ").");
|
||||||
|
this.dispatch("disconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSocketError(evt) {
|
_onSocketError(evt) {
|
||||||
console.error("Connection error: ", evt);
|
console.error("Connection error: ", evt);
|
||||||
|
this.dispatch("connectionError");
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSocketMessage(evt) {
|
_onSocketMessage(evt) {
|
||||||
|
|
@ -76,16 +87,19 @@ class Client {
|
||||||
const msg = JSON.parse(msgString);
|
const msg = JSON.parse(msgString);
|
||||||
|
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
// Response to "init" command
|
// Response to 'init' command (doesn't have much content, I guess)
|
||||||
case "init":
|
case "init":
|
||||||
// TODO
|
|
||||||
console.log("Got init response: ", msg);
|
console.log("Got init response: ", msg);
|
||||||
|
this.dispatch("initialized");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Incoming chat message
|
// Incoming chat message
|
||||||
case "message":
|
case "message":
|
||||||
// TODO
|
console.log("Received chat message from '" + msg.from + "', text '" + msg.text + "'");
|
||||||
console.log("Got message event: from '" + msg.from + "', text '" + msg.text + "'");
|
this.dispatch("receivedMessage", {
|
||||||
|
from: msg.from,
|
||||||
|
text: msg.text,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// TODO Topic change, user join/leave, error, ...
|
// TODO Topic change, user join/leave, error, ...
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class to implement an event system in any class. Events can be dispatched and
|
||||||
|
* subscribed/unsubscribed. Events can have multiple registered callbacks.
|
||||||
|
*/
|
||||||
|
class EventDispatcher {
|
||||||
|
constructor() {
|
||||||
|
this._events = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch a named event. Calls all callbacks that are subscribed to this event.
|
||||||
|
*/
|
||||||
|
dispatch(eventName, data = null) {
|
||||||
|
if (this._events[eventName]) {
|
||||||
|
this._events[eventName].forEach((callback) => {
|
||||||
|
callback(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to an event.
|
||||||
|
*/
|
||||||
|
on(eventName, callback) {
|
||||||
|
if (!this._events[eventName]) {
|
||||||
|
this._events[eventName] = [];
|
||||||
|
}
|
||||||
|
this._events[eventName].push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe from an event. Not sure how to unsubscribe anonymous functions though.
|
||||||
|
* If callback is not found, nothing happens.
|
||||||
|
*/
|
||||||
|
off(eventName, callback) {
|
||||||
|
if (this._events[eventName]) {
|
||||||
|
this._events[eventName] = this._events[eventName].filter(item => item !== callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,4 +7,21 @@ let client;
|
||||||
(function() {
|
(function() {
|
||||||
const wsUri = AppSettings.serverWsUri;
|
const wsUri = AppSettings.serverWsUri;
|
||||||
client = new Client(wsUri);
|
client = new Client(wsUri);
|
||||||
|
|
||||||
|
// Test events
|
||||||
|
client.on("initialized", () => {
|
||||||
|
console.log("UI: Connection initialized!");
|
||||||
|
|
||||||
|
// Send a test message
|
||||||
|
client.sendChatMessage("Meow meow! :3");
|
||||||
|
});
|
||||||
|
client.on("disconnected", () => {
|
||||||
|
console.log("UI: Connection closed!");
|
||||||
|
});
|
||||||
|
client.on("connectionError", () => {
|
||||||
|
console.log("UI: Connection error! :()");
|
||||||
|
});
|
||||||
|
client.on("receivedMessage", (msg) => {
|
||||||
|
console.log("UI: Message from '" + msg.from + "', text: '" + msg.text + "'");
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue