Skip to content

Instantly share code, notes, and snippets.

@kvnam
Last active May 22, 2019 02:39
Show Gist options
  • Save kvnam/3ddf6017045027ecab6dee8c6e519706 to your computer and use it in GitHub Desktop.
Save kvnam/3ddf6017045027ecab6dee8c6e519706 to your computer and use it in GitHub Desktop.
ReactChat-WebSocket
import WebSocket from 'isomorphic-ws';
const WS_URL = process.env.REACT_APP_WEBSOCKET_URL || "";
let WSService = null;
class WebSocketService {
constructor() {
this.websocket = null;
this.messageListeners = [];
this.isOpen = false;
}
/**
* Set up WebSocket connection for a new user and
* basic listeners to handle events
*/
initSocket = () => {
this.websocket = new WebSocket(WS_URL);
this.websocket.onopen = this.onConnOpen;
this.websocket.onmessage = this.onMessage;
this.websocket.onclose = this.onConnClose;
}
/**
* Show connection status to us in the log
*/
onConnOpen = () => {
this.isOpen = true;
console.log('Websocket connected!');
}
/**
* Log lost connection for now
*/
onConnClose = () => {
console.log('Websocket closed!');
}
/**
* Used by application to send message to the WebSocket API Gateway
* @param routeKey The route key for WebSocket API Gateway
* @param message String message
* message {
* room,
* type,
* msg,
* username,
* for
* }
*/
sendMessage = (routeKey, message) => {
if(this.websocket && this.isOpen){
this.websocket.send(JSON.stringify({
rcaction: routeKey,
rcmsg: JSON.stringify(message)
}));
}else{
console.log(`Websocket connection not found!!`);
}
}
/**
* Used by application to register different listeners for
* different message types
* @param room Room name
* @param type Message type ['all', 'pm', 'userlist', 'useradd']
* @param listener Function to handle message type
*/
addMessageListener = (room, type, listener) => {
if (!type || !room || typeof listener !== 'function') {
return;
}
this.messageListeners.push({
room,
type,
listener
});
}
/**
* Handler that receives the actual messages from the WebSocket API
* For now it simply returns the parsed message body to the appropriate
* registered handler
* @param data Message body received from WebSocket
*/
onMessage = (data) => {
if (data) {
const message = JSON.parse(data.data);
const typeListener = this.messageListeners.find(listener => listener.type === message.type);
if (typeListener && typeof typeListener.listener === "function") {
typeListener.listener(message);
} else {
console.log('No handler found for message type');
}
}
}
static initWSService() {
if (!WSService) {
WSService = new WebSocketService();
WSService.initSocket();
return WSService;
}
return WSService;
}
}
export const getWSService = WebSocketService.initWSService;
import { getWSService } from './WebSocket';
interface UserType {
username: string
room: string
joined? : Date
last_active? : Date
}
let UserService: Users | null = null;
/**
* User class to maintain user state
*/
class Users {
private userList : [UserType]
private socketConnection : WebSocket | null
constructor(){
this.userList = [{
username: '',
room: ''
}];
this.socketConnection = null;
}
/**
* Add a new user to the room and initiate WebSocket connection
* @param user User object
* @returns Status string
*/
addUser = (user: UserType): boolean => {
if(this.checkUsername(user.username)){
const userVal = {
username: user.username,
room: user.room,
joined: new Date(),
last_active: new Date()
};
this.userList.push(userVal);
//Initiate the WebSocket connection for the user
this.socketConnection = getWSService();
//Add a timeout to allow WebSocket connection to open
const timeout = setTimeout(() => {
if(this.socketConnection){
//Add user details to Mongo DB
getWSService().sendMessage("useradd", userVal);
}
}, 2000);
return true;
}else{
return false;
}
}
...
/**
* Checks if user name exists, across rooms
* @param username
* @todo Change this to an API call
*/
checkUsername = (username: string): boolean => {
const userIndex = this.userList.findIndex((userObj: UserType) => {
return username === userObj.username;
});
if(userIndex >= 0) return false;
return true;
}
....
static initUserService = (): Users => {
if(!UserService){
UserService = new Users();
return UserService;
}
return UserService;
}
}
export const getUserService = Users.initUserService;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment