express.js 4 and sockets with express router

后端 未结 5 1770
灰色年华
灰色年华 2020-12-05 00:58

I\'m trying to create a really simple node API using express.js 4 but I need a few \'realtime\' events for which I added socket.io. I\'m fairly new to both so I\'m likely m

相关标签:
5条回答
  • 2020-12-05 01:26

    Supposing you want to access the SocketIO from anywhere in your application, not just in the router, you could create a singleton for it. This is what works for me:

    //socket-singletion.js
    
    var socket = require('socket.io');
    
    var SocketSingleton = (function() {
      this.io = null;
      this.configure = function(server) {
        this.io = socket(server);
      }
    
      return this;
    })();
    
    module.exports = SocketSingleton;
    

    Then, you need to configure it using your server:

    //server config file
    
    var SocketSingleton = require('./socket-singleton');
    var http = require('http');
    var server = http.createServer(app);
    SocketSingleton.configure(server); // <--here
    server.listen('3000');
    

    Finally, use it wherever you want:

    //router/index.js
    
    var express = require('express');
    var router = express.Router();
    var SocketSingleton = require('../socket-singleton');
    
    /* GET home page. */
    router.get('/', function(req, res, next) {
      setTimeout(function(){
        SocketSingleton.io.emit('news', {msg: 'success!'});
      }, 3000);
      res.render('index', { title: 'Express' });
    });
    
    module.exports = router;
    
    0 讨论(0)
  • 2020-12-05 01:32

    One option is to pass it in to req object.

    app.js:

    var express = require('express');
    var path = require('path');
    var logger = require('morgan');
    var api = require('./routes/api');
    var app = express();
    var io = require('socket.io').listen(app.listen(3000));
    
    app.use(logger('dev'));
    app.use(express.static(path.join(__dirname, 'public')));
    
    io.sockets.on('connection', function (socket) {
        console.log('client connect');
        socket.on('echo', function (data) {
            io.sockets.emit('message', data);
        });
    });
    
    // Make io accessible to our router
    app.use(function(req,res,next){
        req.io = io;
        next();
    });
    
    app.use('/api', api);
    
    // error handlers omitted
    
    module.exports = app;
    

    ./routes/api.js:

    var express = require('express');
    var router = express.Router();
    
    router.put('/foo', function(req, res) {
        /* 
          do stuff to update the foo resource 
          ...
         */
    
        // now broadcast the updated foo..
        req.io.sockets.emit('update', foo); 
    });
    
    module.exports = router;
    
    0 讨论(0)
  • 2020-12-05 01:36

    One more option is to use req.app.

    app.js

    const express = require('express');
    const path = require('path');
    const logger = require('morgan');
    const api = require('./routes/api');
    
    const app = express();
    const io = require('socket.io').listen(app.listen(3000));
    
    // Keep the io instance
    app.io = io;
    
    app.use(logger('dev'));
    app.use(express.static(path.join(__dirname, 'public')));
    
    // ...
    
    app.use('/api', api);
    
    module.exports = app;
    

    routes/api.js

    const express = require('express');
    const router = express.Router();
    
    router.put('/foo', function(req, res) {
        /*
         * API
         */
    
        // Broadcast the updated foo..
        req.app.io.sockets.emit('update', foo);
    });
    
    module.exports = router;
    
    0 讨论(0)
  • 2020-12-05 01:50

    I've modified your files a little bit, may you check if it works?

    You can pass the io you've defined to your routes like below;

    require('./routes/api')(app,io); 
    

    I didn't test the Socket.IO parts but there is no syntax error and routes also working.

    server.js file:

    var express = require('express');
    var app = express();
    var path = require('path');
    var logger = require('morgan');
    
    var io = require('socket.io').listen(app.listen(3000));
    
    app.use(logger('dev'));
    app.use(express.static(path.join(__dirname, 'public')));
    
    io.sockets.on('connection', function (socket) {
        console.log('client connect');
        socket.on('echo', function (data) {
        io.sockets.emit('message', data);
     });
    });
    
    require('./routes/api')(app,io); 
    
    console.log("Server listening at port 3000");
    

    api.js:

    module.exports = function(app,io) {
    app.put('/foo', function(req, res) {
    
        /* 
    
          do stuff to update the foo resource 
    
          ...
    
         */
    
    
        // now broadcast the updated foo..
    
        console.log("PUT OK!");
    
        io.sockets.emit('update'); // how?
        res.json({result: "update sent over IO"});
    
    });
    }
    
    0 讨论(0)
  • 2020-12-05 01:50

    I think best way is to set io as a property of req, like below:

    app.use(function(req,res,next){
        req.io = io;
        next();
    });
    
    app.use('/your-sub-link', your-router);
    
    0 讨论(0)
提交回复
热议问题