简体   繁体   中英

Implement socket.io in node.js application controller

good afternoon. I am new to programming sockets in node.js and I need to implement socket.io in a controller of my application. The architecture I have is the following:

The file that starts the server is index.js

const express = require('express');
const app = express();
const port = 3000;
const socketRouter = require('./routes/socket')

app.use(express.json());
  
//Route
app.use('/socket', socketRouter);

app.listen(port, () => {
    console.log(`Server connection on  http://127.0.0.1:${port}`);  // Server Connnected
});

The file where I define the routes is socket.js

const { Router } = require('express');
const { showData } = require('../controllers/socket');

const router = Router();

router.post('/send-notification', showData);

module.exports = router;

And my controller is:

const { response } = require('express');

const showData = (req, res = response) => {
    const notify = { data: req.body };
    //socket.emit('notification', notify); // Updates Live Notification
    res.send(notify);
}

module.exports={
    showData
}

I need to implement socket.io in this controller to be able to emit from it but I can't get it to work. Could you tell me how to do it? Thanks a lot

CLARIFICATION: if I implement socket.io in the main file it works, but I want to have some order and separate things. This is how it works:

const express = require('express');
const app = express();
const port = 3000;

app.use(express.json());

app.post('/send-notification', (req, res) => {
    const notify = { data: req.body };
    socket.emit('notification', notify); // Updates Live Notification
    res.send(notify);
});

const server = app.listen(port, () => {
    console.log(`Server connection on  http://127.0.0.1:${port}`);  // Server Connnected
});

const socket = require('socket.io')(server);

socket.on('connection', socket => {
    console.log('Socket: client connected');
});

You can use the same socket and app (if you need to expose APIs as well) in other files if you want to separate socket messages and REST endpoints by functionality or however you choose to organize it. Here's an example of how this can be done:

Create a new file, let's say controller1.js :

function initialize(socket, app) {
    socket.on('some-socket-message', socket => {
        // Whatever you want to do
    });
    
    app.get('/some-endpoint', (req, res) => {
        // whatever you want to do
    });
}


module.exports = {initialize}

And then add the following to your controller.js

const controller1 = require('path/to/controller1');

...

// At some point after socket and app have been defined
controller1.initalize(socket, app);

This will be the bases of separating your controller however you want, while still using the same socket connection and API port in all of your controllers. You can also refactor the initialize method into different methods, but that would be at your own discretion and how you want to name functions, etc. It also does not need to be called initalize , that was just my name of preference.

thanks for answering but I'm not clear. Where do I do the initial configuration of the socket? I don't have such configuration in the controller

Move your socket.io code to its own module where you can export a method that shares the socket.io server instance:

// local socketio.js module

const socketio = require('socket.io');

let io;
modules.exports = {
   init: function(server) {
       io = socketio(server);
       return io;
   },
   getIO: function() {
       if (!io) {
          throw new Error("Can't get io instance before calling .init()");
       }
       return io;
   }
}

Then, initialize the socketio.js module in your main app file:

const express = require('express');
const app = express();
const port = 3000;


app.use(express.json());
  
const server = app.listen(port, () => {
    console.log(`Server connection on  http://127.0.0.1:${port}`);  // Server Connnected
});

// initialize your local socket.io module
const sio = require('./socketio.js');
sio.init(server);

// now load socket.io dependent routes
// only after .init() has been called on socket.io module
const socketRouter = require('./routes/socket')
app.use('/socket', socketRouter);

Then, anywhere you want to access the socket.io server instance, you can require("./socketio.js") and use the .getIO() method to get the socket.io instance:

// use correct path to socketio.js depending upon where this module 
// is located in the file system
const io = require("../../socketio.js").getIO();

// some Express route in a controller
const showData = (req, res) => {
    const notify = { data: req.body };

    // send notification to all connected clients
    io.emit('notification', notify);
    res.send(notify);
};

module.exports= {
    showData
};

Note: A typical socket.io usage convention on the server is to use io as the server instance and socket as an individual client connection socket instance. Please don't try to use socket for both. This makes it clear that io.emit(...) is attempting to send to all connected clients and socket.emit() is attempting to send to a single connected client.

Also note that if your route is triggered by a form post where the browser itself sends the form post, then that particular client will not receive the results of io.emit(...) done from that form post route because that browser will be in the process of loading a new web page based on the response of the form post and will be destroying its current socket.io connection. If the form post is done entirely via Javascript using an Ajax call, then that webpage will stay active and will receive the results of the io.emit(...) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM