13

I have created a new Express application. It generated app.js for me and I have then created the following index.js bringing in socket.io:

var app = require('./app');
server=app.listen(3000);

var io = require('socket.io');
var socket = io.listen(server, { log: false });

socket.on('connection', function (client){
    console.log('socket connected!');
});

Can anyone advise how I would access socket.io within the routes files?

For reference, the default generated app.js is below:

var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

/// catch 404 and forwarding to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});


module.exports = app;
Ben
  • 6,026
  • 11
  • 51
  • 72
  • Best solution here: http://stackoverflow.com/questions/37559610/socket-io-emit-on-express-route/37560779#37560779 – mdv Jun 01 '16 at 14:26

3 Answers3

35

SocketIO does not work with routes it works with sockets.

That said you might want to use express-io instead as this specially made for this or if you are building a realtime web app then try using sailsjs which already has socketIO integrated to it.

Do this to your main app.js

app = require('express.io')()
app.http().io()

app.listen(7076)

Then on your routes do something like:

app.get('/', function(req, res) {
    // Do normal req and res here
    // Forward to realtime route
    req.io.route('hello')
})

// This realtime route will handle the realtime request
app.io.route('hello', function(req) {
    req.io.broadcast('hello visitor');
})

See the express-io documentation here.

Or you can do this if you really want to stick with express + socketio

On your app.js

server = http.createServer(app)
io = require('socket.io').listen(server)
require('.sockets')(io);

Then create a file sockets.js

module.exports = function(io) {

    io.sockets.on('connection', function (socket) {
        socket.on('captain', function(data) {
            console.log(data);
            socket.emit('Hello');
        });
    });
};

You can then call that to your routes/controllers.

androo
  • 939
  • 9
  • 16
majidarif
  • 18,694
  • 16
  • 88
  • 133
  • 4
    Since express.io uses an older version of express I suggest you also have a look at the following way: http://stackoverflow.com/questions/24222483/socket-io-1-0-express-4-2-no-socket-connection/24222869#24222869 Although I do not understand clearly what the author is trying to explain in the answer, but I would like for more people to explore and help solve this topic for the better. – Chetan Bhasin Jul 05 '14 at 20:46
  • 15
    What does it mean "You can then call that to your routes/controllers." ? – Markus Pint Sep 12 '14 at 08:51
  • 14
    Express.io seems to be unmaintained. – Dirk May 26 '15 at 19:18
  • Please give complete examle with routes and controllers. – Stephan Kristyn Nov 24 '15 at 16:22
  • I don't think the express + socketio example will work because in order to do it this way you access the socket.io server (io) in every file you are trying to use sockets.js – Nick Pineda Feb 21 '16 at 05:01
  • It would be nice to see a full example with calling in a router with a form in the templates. – Lanti Jul 14 '16 at 20:17
7

The route:

const Router = require('express').Router

const router = new Router();

router.get('/my-route', (req, res, next) => {
    console.log(req.app.locals.io) //io object
    const io = req.app.locals.io
    io.emit('my event', { my: 'data' }) //emit to everyone
    res.send("OK")
});

module.exports = router

The main file:

const app = require('express')()
const server = require('http').Server(app);
const io = require('socket.io')(server)
const myroute = require("./route") //route file dir

app.use(myroute);

server.listen(3000, () => {
    console.log('¡Usando el puerto 3000!');
});

app.locals.io = io
Armando Rueda
  • 73
  • 1
  • 4
0

I think a better way to do it is to attach the Io server to response object In the first middleware .per the way express is designed the Io server will be available to your subsequent routes.

Check this link

fcdt
  • 2,371
  • 5
  • 14
  • 26
blackhat
  • 11
  • 1
  • 3
  • It would be better if you would have posted an example instead of a link. That URL takes us to something that assumes we are using an express app generator, of course we could only take the important stuff and use it in our project; In my opinion it could be better to just post a generic working example. – Herii Jul 28 '21 at 14:01