How to separate all of socket.io to a different file - javascript

Right now, I have app.js where I have my usual code and my socket.io code. But what I want to do is, separate every single code of socket.io into 1 different file and require that socket.io code from the different file into my main app.js. Is there any way to do it writing 2/3 lines of code into my app.js to require socket.io from a different file?
Note: I do not want to write any of my socket.io code into my app.js so I do not know if it would be possible to require('....') it into my app.js from a different file. Ideally want to separate everything within io.on('connection'){}
const express = require('express');
const http = require('http'); // socket.io is created upon http server. A way to create server
const cors = require('cors');
const {Server} = require('socket.io');
const app = express();
app.use(cors());
const server = http.createServer(app); // this is to create http server with express for socket.io
const io = new Server(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"]
}
});
io.on("connection", (socket) => {
socket.on("newUser", (username) => {
addNewUser(username, socket.id);
console.log('connect print: '); printUsers();
})
socket.on("disconnect", () => {
removeUser(socket.id);
console.log('disconnect print: '); printUsers();
});
})
server.listen(3001, () => {
console.log('server listening on port 3001');
})

There would be a few way to do this but something like below should work.
In your new file, use module.exports to export an object containing any functions or objects you want to export:
//socketio.js
module.exports = {
getIo: (server) => {
const io = new Server(server, {
//...
});
io.on("connection", (socket) => {
//...
}
//your other functions
return io;
}
}
Then in your app.js, require it and use the object's properties:
//app.js
const socketio = require('./socketio.js');
//after creating your server etc
const io = socketio.getIo(server);

Related

Why am I not able to access the express server from a different file?

I have set up an express server as follows (inside of server.js ) :
const app = express();
.........
.....
const PORT = process.env.PORT || 5000;
const server = app.listen(PORT, () =>
console.log(`Server started on port ${PORT}`)
);
module.exports = server;
Inside of another file socket.js:
const server = require("./server");
const socketio = require("socket.io");
const io = socketio(server);
io.on("connection", function (socket) {
console.log("A user just joined!");
socket.on("disconnect", () => {
console.log("A socket just left!");
});
});
For some reason I get an error in my console while trying to connect to the socketio on the client:
GET http://localhost:3000/socket.io/?EIO=3&transport=polling&t=N8-d7Q4 404 (Not Found)
The error does not occur if I execute everything in a single file (without exporting the server):
const PORT = process.env.PORT || 5000;
const server = app.listen(PORT, () =>
console.log(`Server started on port ${PORT}`)
);
const socketio = require("socket.io");
const io = socketio(server);
io.on("connection", function (socket) {
console.log("A user just joined!");
socket.on("disconnect", () => {
console.log("A socket just left!");
});
});
I don't understand what's wrong. Does module.exports not work with the express server or is this is a socketio issue ?
It appears you're not loading socket.js at all. When you had only the one file, you just did node app.js and that would work fine. But, if you do node app.js with your two files, then there's nothing to ever load socket.js at all. In fact, the way you have the two files laid out, you would have to do:
node socket.js
to initialize things. Then, socket.js does a require('./app.js') to get app.js loaded.
I was wondering if it's impossible to module.exports = server at all
Yes, you can freely export the server and you are exporting it.
Another way of doing things is to still have app.js be your main file that you load to start up your app and you load socket.js from there and pass it the server object so it can use it.
// app.js
const server = const server = app.listen(...);
// load socket.js and pass it our server
require('./socket.js')(server);
Then in socket.js:
// socket.js
const socketio = require("socket.io");
module.exports = function(server) {
const io = socketio(server);
// rest of your module code here
}

Socket.io global sending Function - Node.js

I build a simple node.js / socket.io app.
I need for emitting events a module, that can be accessible through other modules so I can send socket messages when there is for example a new database entry.
Something like this:
function sendWebsocketEvent (whereToSend, EventName, Payload) {
io.in(whereToSend).emit(EventName, Payload)
}
How can I handle that?
I've tried that:
-- app.js --
// Websockets
var http = require('http').createServer(app)
var io = require('socket.io')(http)
http.listen(3000, function () {
console.log('listening on Port *:3000')
})
require('./WebSockets/socketInit')(io)
-- socketInit.js --
module.exports = (ioInput) => {
const io = ioInput
return io
}
-- sendSockets.js --
const io = require('./socketInit')
module.exports = {
sendWebsocketEvent (whereToSend, EventName, Payload) {
io.in(whereToSend).emit(EventName, Payload)
}
}
And I tried to call this function at another module:
const sendSockets = require('../WebSockets/sendSockets')
.
.
.
sendSockets.sendWebsocketEvent('user', 'databaseUpdate', 'dataToSend')
.
.
.
But this doesn't work.
Is there an other way for getting this done?
Chris
Inside Server.js
const express = require('express');
const app = express();
const server = require('http').createServer(app)
const io = socket.listen(server);
global.io = io;
const port = process.env.PORT || 5500;
server.listen(port, () => console.log(`%s 🚀 Server is listening on port ${port}`, chalk.green('✓')));
// socket io connection
let interval;
io.on("connection", socket => {
console.log("New client connected");
if (interval) {
clearInterval(interval);
}
});
And emit where you want just like that
global.io.emit('EventName', data);

Use socket.io across diffrent routes in node.js

I have different routes in my node js application and now i want to use socket.io in every route to make my node and react js application realtime. But, i have the below structure of my node js application.
router.js
const express = require('express');
const router = express.Router();
const worksheetController = require('../controllers/worksheet');
const attendenceController = require('../controllers/attendence');
router.route('/worksheets')
.get(
worksheetController.getWorksheet
)
.post(
worksheetController.validateWorksheet,
worksheetController.addWorksheet,
attendenceController.markAttendence
);
router.route('/attendances')
.get(
attendenceController.getAttendance
);
module.exports = router;
server.js
const express = require('express');
const router = require('./router');
const app = express();
app.use('/api', router);
app.listen('5000', () => {
console.log('Listening on port');
});
module.exports = app;
How can I use socket.io for different routes?
You don't need to correlate express routes and socket.io events. They are two different things. Perhaps you can add the related logic in the controllers and call the functions from socket.io events as you have done with express routes.
eg:
const worksheetController = require('../controllers/worksheet');
io.on('connection', function (socket) {
socket.on('my event', function (data) {
const myData = worksheetController.getDataForOtherEvent(data);
console.log(myData);
});
});

Is this the correct way to share a instance of a Redis client in Express?

Due to I have the application routes dedined in separated scripts I need a way to share the same Redis client across all of them. Is this the correct way of doing it ?
app.js
const express = require('express');
const app = express();
var redis = require("redis"),
client = redis.createClient();
app.use((req, res, next) => {
req.redis = client;
next();
});
// load routes
app.listen(3000, () => console.log('Example app listening on port 3000!'));
... other js file
app.get('/xyz', (req, res) => {
var redis = red.redis;
// use redis
});
You're un-necessarily passing your client instance to every request regardless of if it's needed.
I use a pretty standard controller which you can then require() as needed, example below.
var redis = require('redis')
.createClient(...);
redis.on('connect', function() {
console.log('Redis server online.');
});
module.exports = redis;
Then whenever you want to access it
var redis = require('./app/controllers/redis');
// redis => Redis client instance

How can I emit events to connected sockets using socket.io from within my Express 4 routes?

This is a question other people have asked, but I can't manage to benefit from the answers they've been given, due to the different Express setup I have.
I've got socket.io implemented and working in a simple way on my server. This is how it works:
In bin/www:
#!/usr/bin/env node
var debug = require('debug')('gokibitz');
var app = require('../../server');
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
var io = require('socket.io').listen(server);
io.on('connection', require('../routes/socket.js'));
All my routes and other Express setup is in ../../server.js.
var routes = require('./server/routes/index');
var user = require('./server/routes/user');
...
app.use('/', routes);
app.use('/api/user/', user);
...
app.use('*', routes);
Then in ../routes/socket.js, I've got this boilerplate:
module.exports = function (socket) {
socket.emit('send:news', { hello: 'world' });
setInterval(function () {
socket.emit('send:time', {
time: (new Date()).toString()
});
}, 1000);
return socket;
};
This is working beautifully, I might add. But now I want to be able to emit events from the various routes in my quite-ordinary Express app, and I can't for the life of me figure out the right way to get a reference to the socket object I need.
Example: when a user makes a comment, I'd like to emit an event to all connected users notifying them of the new comment. From my routes file (./server/routes/user.js), how can I get access to the object I need to emit events?
Here's a skeleton of the relevant bits from a route file:
var express = require('express');
var router = express.Router();
router.post('/', function (req, res) {
...
});
module.exports = router;
The only place I can access it is in the ../routes/socket.js file, which is useless.
All of the routes are set in a app.js before there's any io or socket object to pass in.
Should I be able to require('socket.io') and use it somehow to emit to all connected sockets?
Is there a sensible way to store the connected sockets on ../routes/socket.js so it can be required and emitted to from other routes?
Can anyone steer me in the right direction?
I was able to ultimately get things working using this example:
https://github.com/expressjs/generator/issues/45#issuecomment-53719435
I created a new file called server/io.js:
var io = require('socket.io')();
io.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
module.exports = io;
Then I updated server/bin/www to this:
#!/usr/bin/env node
var debug = require('debug')('gokibitz');
var app = require('../../server');
var io = require('../io');
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
io.attach(server);
Then, in my route, I use this:
var io = require('../io');
...
io.emit(...);
The missing piece for me, at least, was the ability to create the io object separately, return the correct object, then use io.attach(server) inside bin/www to start it up at the right point.
Hopefully this will help someone else following in my footsteps.
I think you are confused with the concepts. The socket.io lib uses or emulate a websocket (bidirectional socket) with the client, and have not relation with routes.
You can send a notification to all sockets using the io object:
io.emit('message_to_all', true);
You have to an array on io.sockets, with all sockets.
You can uses namespaces or rooms to, I recomend you learn the documentation:
http://socket.io/docs/rooms-and-namespaces/#
Add something:
If you want to send a message to all people in the same route, you can join to a channel with the same name of the path.
For example, in the client:
var socket = io(window.location.href); // Or route..
And the server:
var nsp = io.of('/the/specific/route');
nsp.on('connection', function(socket){
// ...
});
nsp.emit('message_to_all_in_route', data);
About the last question editing:
You can send the io object in request or response object to routes, using the Express midleware API:
For example:
#!/usr/bin/env node
var debug = require('debug')('gokibitz');
var app = require('../../server');
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
var io = require('socket.io').listen(server);
app.use(function (req, res, next) {
res.io = io;
next();
});
io.on('connection', require('../routes/socket.js'));
And in the route:
route.post('/post/:id/comments', function (req, res) {
// Do your logic
var postio = res.io.of('/post/' + req.params.id);
postio.emit('new_comment', commentData);
});
As I said in my comment, you can send to all connected clients with:
io.emit(msg, data);
This will require access to the io object that you created in your first module. The usual way to share that with your module with your routes modeule would be to export a method from the routes module that lets you pass it the io object and then after you've required in the routes module and created the io object, you can just call that method to pass the io object to the routes module and it can save it locally for future use.
io is just a shared object like the app object is. If you want a module to be able to use a shared object, the usual way is that you call some method in that module to share with it some objects that it can then use.
I have made a new file sockets.js in that file:
var socketio = require('socket.io');
var io;
module.exports = {
socketServer: function (app) {
io = socketio.listen(app);
io.on('connection', function (socket) {
console.log(Object.keys(users));
socket.on('message', function (data) {
io.emit('updateChat', 'Hello World!')
});
});
}
}
And in my app.js:
var express = require('express');
var app = express();
var http = require('http').createServer(app);
var port = process.env.PORT || 3000;
var io = require('./sockets').socketServer(http);
http.listen(port, function () {
console.log('SERVER RUNNING.. PORT: ' + port)
});
This is working for me. Good Luck!

Categories