Last active
May 22, 2019 02:39
-
-
Save kvnam/3ddf6017045027ecab6dee8c6e519706 to your computer and use it in GitHub Desktop.
ReactChat-WebSocket
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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