Socket doesn't emit within route

I'm building a web app where the view needs to be updated on a data change. For this purpose I'm using socket.io. This is the setup in the server.js file:

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

/* WEB SOCKET INITIALISATION
----------------------------------------- */
io.on('connection', function(socket) {
  io.emit('new connection', 'new connection');

  socket.on('disconnect', function () {
    io.emit('offline', 'offline')
  });
});

When looking into my console, it log's 'new connection' as soon as I'm on the page. Now I want to use the socket in one of the routes i've made. To make this possible I bind io to the place where i require the route, like this:

const dashboardRouter = require('./routes/dashboard')(io);

This is how a part of the route looks like:

/* MAKE SOCKET.IO ACCESSABLE
--------------------------------------------------------------- */
module.exports = function(io) {

  /* INDEX ROUTE
  -------------------------------------------------------------- */
  router.get('/', account.checkSession, playwalls.statistics, playwalls.getYours, function(req, res, next) {
    io.emit('update', 'testen');
    res.locals.username = req.session.username;
    res.render('dashboard/index');
  });

  /* EXPORT ROUTER
  --------------------------------------------------------------- */
  return router;

}

The problem is that when I emit update, it doesn't log in the console. When I do console.log(io) inside the route, it looks like socket.io is available though. I get no errors inside the terminal console.

This is what the client side JavaScript file looks like:

(function() {

  const socket = io();

  socket.on('update', function(data) {
    console.log('Works');
  });

  socket.on('new connection', function(data) {
    console.log(data);
  });

}());

What am I doing wrong here? How can I make sure that the socket emits the message? Hope someone can help me with this!

Thanks in advance.

Upvotes: 0

Views: 351

Answers (1)

jfriend00
jfriend00

Reputation: 708106

This route:

  router.get('/', account.checkSession, playwalls.statistics, playwalls.getYours, function(req, res, next) {
    io.emit('update', 'testen');
    res.locals.username = req.session.username;
    res.render('dashboard/index');
  });

Will broadcast to all the other connected pages, but will not show anything for the particular user that triggered this route. That's because the user that triggered this route is in the middle of requesting and loading a page and they are not yet connected to socket.io.

The sequence of operations for the user who made this requests is as follows:

  1. Browser closes down previous web page which includes disconnecting socket.io and shutting down Javascript.
  2. Browser requests / URL.
  3. Server calls your route handler for that URL.
  4. Your route handler calls io.emit() which sends to all currently connected clients, but the client making this request is not currently connected.
  5. Route handler renders the page and sends it back to the browser.
  6. Browser receives and renders the page
  7. Browser runs Javascript in the page, resulting in socket.io connection being made.

As you can see from this sequence, the browser making the request is not connected with socket.io when you call io.emit(). Basically, you can't emit to the page that is being rendered in the same route that renders it.

Upvotes: 1

Related Questions