node.js call ws.send from controller - javascript

i want to send a websocket, using express-ws out from a different controller, not by route and I have the following code in the server.js:
var SocketController = require('./routes/ws.routes');
var app = express();
var server = require('http').createServer(app);
var expressWs = require('express-ws')(app);
app.ws('/', SocketController.socketFunction);
the SocketController looks like that:
exports.socketFunction = function (ws, req) {
ws.on('message', function(msg) {
console.log(msg);
ws.send("hello");
});
}
Is it possible to call the
ws.send()
event from another controller? How do i get the "ws" object?
thanks!

You will have to store your sockets in memory. To access stored sockets from different modules, you can store references for these sockets in a separate module.
For example, you can create a module socketCollection that stores all the active sockets.
socketCollection.js:
exports.socketCollection = [];
You can import this module where you define your web socket server:
var socketCollection = require('./socketCollection');
var SocketController = require('./routes/ws.routes');
var app = express();
var server = require('http').createServer(app);
var expressWs = require('express-ws')(app);
expressWs.getWss().on('connection', function(ws) {
socketCollection.push({
id: 'someRandomSocketId',
socket: ws,
});
});
app.ws('/', SocketController.socketFunction);
Now every time new client connects to the server, it's reference will be saved to 'socketCollection'
You can access these clients from any module by importing this array
var socketCollection = require('./socketCollection');
var ws = findSocket('someRandomSocketId', socketCollection);
var findSocket = function(id, socketCollection) {
var result = socketCollection.filter(function(x){return x.id == id;} );
return result ? result[0].socket : null;
};

Related

Configuring socket.io for node.js application

I have a few questions about configuring socket.io for my node.js application.
When requiring var socket = require('socket.io')( /* HERE */ ), do I need to input the port my server listens where the /* HERE */ is at?
Right below the above line, I have another require function, for a .js file that contains a few constants and a function (see below). When I try to refer to 'socket' in that file it says it's undefined. But since this line is below the require line for the socket.io middleware seen above, why does it say 'undefined'?
const numbers = '1234'
function asd(req,res,next) {
socket.emit('a')
}
module.exports = {
asd
}
For configuring client-side socket.io, I added this line:
var socket = io.connect('https://mydomain')
Do I need to say 'mydomain:port' or is 'mydomain' enough?
This is how you use socket.io
var http = require('http');
var express = require('express');
var path = require('path');
var app = http.createServer();
var io = require('socket.io')(app);
var port = 8081;
io.on('connection', function(socket){
socket.on('event1', function (data) {
console.log(data);
socket.emit('event2', { msg: 'delivered' });
});
});
app.listen(port);
Answer to your second question
Yes, you will need to specify the port you are using
<script src="socket.io.js"></script>
<script>
var socket = new io.Socket();
socket.connect('https://mydomain:8081')
socket.on('your_event',function() {
console.log('your_event receivid from the server');
});
</script>
Here socket will connect to port 8081
This is a simple server side code
var http = require('http');
var io = require('socket.io');
var port = 8081;
// Start the server at port 8081
var server = http.createServer();
server.listen(port);
var socket = io.listen(server);
// example listener
socket.on('event_2', function(client){
console.log('event_2 received');
});
// example emitter
socket.emit('event_1', { hello: 'world' });

Use JSON Object for Function Pointer Mapping in NodeJS

I'm trying to learn Socket.io and I'm a beginner in NodeJS.
I'm using JSON object as a kind of key-value store for mapping callback function with relevant event names. May be there is some other alternative to do it efficiently which I don't know. The problem is in the code below, when I call bob.printName() it prints the JSON object perfectly. But when I call the same function using the callbacks['connection'](), it says the JSON object is undefined. I would like to know the reason of that and also love to know any other efficient alternatives like PHP like array indexing.
/***
** index.js
***/
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var User = require('./User');
var bob = new User();
var callbacks = {
'connection': bob.printName
};
io.on('connection', function(socket){
bob.printName();
callbacks['connection']();
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
/***
** User.js
***/
var jsonObj = null;
function User() {
this.jsonObj = {
type: 'type',
body: 'body'
};
}
User.prototype.printName = function(){
console.log(this.jsonObj);
}
module.exports = User;

javascript class variable scope confusion (socket.io events)

I'm using node with express and socket.io to create a game server. I've put the game server in a extra module.
I have the problem that I can't access the game server object within the io event.
How do I solve this problem or should I structure my project differently?
// gameServer.js
'use strict'
var io = require('socket.io');
var socketioJwt = require('socketio-jwt');
var config = require('../config.js');
class GameServer {
constructor(http) {
this.io = new io(http);
this.connectedUsers = [];
this.initSocket();
}
initSocket() {
console.log('users', this.connectedUsers);
this.io.on('connection', this.onConnection);
}
onConnection(socket) {
console.log('users', this.connectedUsers); // undefined
}
}
I initialize the server like that:
'use strict'
var express = require('express');
var app = express();
var http = require('http').Server(app);
// init game server
var gameServerApp = new GameServer(http);
http.listen(3000, function() {
console.log('listening on *:3000');
});
I assume this is a common question but I can't figure out how to solve it.
You can bind this to this.onConnection
initSocket() {
console.log('users', this.connectedUsers);
this.io.on('connection', this.onConnection.bind(this));
}

Socket IO - Socket.emit is sent to all clients

I am creating a game using socket io. A player connects like this:
var playerName = document.getElementById("name").value;
socket.emit('setup player', {
name : playerName
});
Then on the server, the player is setup and his information is sent back to the client:
function onSetupPlayer(data) {
...
var newPlayer = new Player(x, y, color, data.name,
this.id, scale);
socket.emit('setup game', {
localPlayer : newPlayer
});
...
sockets[this.id] = socket;
}
The following call:
socket.emit('setup game', {
localPlayer : newPlayer
});
Should send the setup data only back to the client that requested the setup to be done originally. However the setup call gets send to everyone in the lobby.
Could this have anything to do with the fact that I am using localhost to test it? I am also testing it on the same machine by using different tabs. If this is what is causing the issue, is there a way to resolve it? Since this is pretty annoying when testing my game.
EDIT:
Initialization:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var socket = require('socket.io')(http);
var path = require('path');
var io = require('socket.io')(80);
...
var setEventHandlers = function() {
socket.sockets.on("connection", onSocketConnection);
};
Listening for connection:
function onSocketConnection(client) {
...
client.on("setup player", onSetupPlayer);
...
};
And on the client side I have this:
var setEventHandlers = function() {
socket.on("setup game", onSetupGame);
...
}
socket.emit send event to everyone excepts this. To send data back to this user try
io.to(socket).emit()

Emit socket from a controller - How to get access to socket server from a controller

Bases
I'm trying to use sockets on my node project. This is the how it basically works :
/
|-> controllers/
| |-> home.js
|-> app.js
|-> sockets.js
/app.js
On app, I call sockets.js to start the socket server :
var express = require('express');
var sockets = require('./sockets');
var app = module.exports = express();
var server = app.listen(config.PORT);
var io = sockets(server);
/sockets.js
On this file I start the socket server, and return io.
var socket = require('socket.io');
module.exports = function(server) {
var io = socket.listen(server);
io.sockets.on('connection', function(socket) {
// Here I can call every socket I want (if I have the socket_id) with this code :
var socket = io.to(socket_id);
socket.emit('message', {});
});
return io;
};
Question
But now, I want to retrieve my io server on my home controller and call a specific socket. I've tried to do this :
/controller/home.js
var io = require('../sockets.js');
module.exports = {
home: function(req, res, next) {
var socket = io.to(socket_id);
socket.emit('message', {});
}
};
But I have this error, cause I don't execute the function (but I don't want create a new socket server here) :
TypeError: Object function (server) {
var io = socket.listen(server);
/*.....*/
return io;
} has no method 'to'
I want to get an access to the io variable returned by this function called on app.js. How Can i get it ?
You could convert sockets.js into an object that exposes your io property. You would also add a function listen that app.js calls during initialization.
// sockets.js
module.exports = {
listen: function(server) {
this.io = socket.listen(server);
//...
return this.io;
}
}
Your controller can then access require('../sockets.js').io, You just need to make sure io is defined at the time you use it, or otherwise make sure app.js calls listen before your controller gets invoked.
You must be convert sockets.js into an object that exposes your io property.
You would also add a function listen that app.js calls during initialization.
Your controller can then access require('../sockets.js').io.

Categories