Use socket.io in controllers

后端 未结 3 1140
离开以前
离开以前 2021-01-30 00:37

I only need socket.io to emit messages to clients, if a new object is inserted to database. So my idea was to emit the message directly fr

相关标签:
3条回答
  • 2021-01-30 01:00

    You can do this very easily you have to only write socket connection in app.js and than you can use socket anywhere you want

    In app.js file put code like below

     var http = require('http').createServer(app);
     const io = require('socket.io')(http);  
    
     io.sockets.on("connection", function (socket) {
     // Everytime a client logs in, display a connected message
     console.log("Server-Client Connected!");
    
     socket.join("_room" + socket.handshake.query.room_id);
    
     socket.on('connected', function (data) {
    
       });
    });
    
    const socketIoObject = io;
    module.exports.ioObject = socketIoObject;
    

    In any file or in controller you can import that object like below

     const socket = require('../app'); //import socket  from app.js
    
          //you can emit or on the events as shown 
     socket.ioObject.sockets.in("_room" + req.body.id).emit("msg", "How are You ?");
    
    0 讨论(0)
  • 2021-01-30 01:06
    You can solve this problem declaring io instance as global variable.
    
    at the last line of my app.js: IoInstance = require("./socket.io")(server);
    
    at the './socket.io' :
    const chatNamespace = require("./namespaces/chat");
    const notificationsNamespace = require("./namespaces/notifications");
    const auth = require("./middlewares/auth");
    
    module.exports = (server) => {
      const io = require("socket.io").listen(server);
    
      io.of("/chats")
        .use(auth)
        .on("connect", (socket) => chatNamespace({ io, socket }));
    
      io.of("/notifications")
        .use(auth)
        .on("connect", (socket) => notificationsNamespace({ io, socket }));
    
      return io;
    };
    
    then, you can use the IoInstance wherever you want, event into your controller. Btw, I could have use it into my namespaces as well, but I've just realized it right now.
    
    example of implementation in the testController.js:
    
    module.exports = async (req, res) => {
      IoInstance.of("/notifications")
        .to("myUserId")
        .emit("sendNotification", ["test", "test1"]);
      return res.send("oioi");
    };
    
    0 讨论(0)
  • 2021-01-30 01:07

    You are trying to invert the flow of control. The way to do it is for your controller to implement an interface (an API) that your server can use to pass control to.

    A simple example would be:

    In mycontroller.js

    // no require needed here, at least, I don't think so
    
    // Controller agrees to implement the function called "respond"
    module.exports.respond = function(socket_io){
        // this function expects a socket_io connection as argument
    
        // now we can do whatever we want:
        socket_io.on('news',function(newsreel){
    
            // as is proper, protocol logic like
            // this belongs in a controller:
    
            socket.broadcast.emit(newsreel);
        });
    }
    

    Now in server.js:

    var io = require('socket.io').listen(80);
    var controller = require('./mycontroller');
    
    io.sockets.on('connection', controller.respond );
    

    This example is simple because the controller API looks exactly like a socket.io callback. But what if you want to pass other parameters to the controller? Like the io object itself or the variables representing end points? For that you'd need a little more work but it's not much. It's basically the same trick we often use to break out of or create closures: function generators:

    In mycontroller.js

    module.exports.respond = function(endpoint,socket){
        // this function now expects an endpoint as argument
    
        socket.on('news',function(newsreel){
    
            // as is proper, protocol logic like
            // this belongs in a controller:
    
            endpoint.emit(newsreel); // broadcast news to everyone subscribing
                                         // to our endpoint/namespace
        });
    }
    

    Now on the server we'd need a bit more work in order to pass the end point:

    var io = require('socket.io').listen(80);
    var controller = require('./mycontroller');
    
    var chat = io
      .of('/chat')
      .on('connection', function (socket) {
          controller.respond(chat,socket);
      });
    

    Notice that we pass socket straight through but we capture chat via a closure. With this you can have multiple endpoints each with their own controllers:

    var io = require('socket.io').listen(80);
    var news_controller = require('./controllers/news');
    var chat_controller = require('./controllers/chat');
    
    var news = io
      .of('/news')
      .on('connection', function (socket) {
          news_controller.respond(news,socket);
      });
    
    var chat = io
      .of('/chat')
      .on('connection', function (socket) {
          chat_controller.respond(chat,socket);
      });
    

    Actually, you can even use multiple controllers for each endpoint. Remember, the controllers don't do anything apart from subscribing to events. It's the server that's doing the listening:

    var io = require('socket.io').listen(80);
    var news_controller = require('./controllers/news');
    var chat_controller = require('./controllers/chat');
    
    var chat = io
      .of('/chat')
      .on('connection', function (socket) {
          news_controller.respond(chat,socket);
          chat_controller.respond(chat,socket);
      });
    

    It even works with plain socket.io (no endpoints/namespaces):

    var io = require('socket.io').listen(80);
    var news_controller = require('./controllers/news');
    var chat_controller = require('./controllers/chat');
    
    io.sockets.on('connection', function (socket) {
        news_controller.respond(socket);
        chat_controller.respond(socket);
    });
    
    0 讨论(0)
提交回复
热议问题