1

I am setting up foundations for a websocket app using node.js, express and socket.io. I decided it would be elegant to place the code that sets up socket.io in a separate module, so my server.js file could be smaller, calling require for socket.io setup duties.

// server.js

// set up ======================================================================
var express = require('express');
var app     = express();
var server  = require('http').Server(app);
var io      = require('socket.io')(server);
var port    = process.env.PORT || 80;

// routes ======================================================================
app.get('/', function (req, res) {
    res.sendFile(__dirname + '/index.html');
});

// socket.io controller ========================================================
require('./app/ws-controller.js')(io);

// launch ======================================================================
server.listen(port, function () {
    console.log('Server listening on port ' + port + '!');
});

In my ws-controller.js file I placed some code to begin experimenting with socket.io.

// app/ws-controller.js
module.exports = function(io) {
    var numClients = 0;
    io.on('connection', function (socket) {
        numClients++;
        console.log(numClients);
    });
}

The client script embedded in index.html is minimal.

// client side script
var port = 80;
var socket = io.connect('http://127.0.0.1:' + port);

Now to the point. Upon opening new browser tabs pointing to localhost, the server logs to the console increasing number numClients. How is that actually working? I was sure that numClients would be out of scope and expected to see an exception on the console. When the callback function bound to on connection events fires it shouldn't see the numClients variable since it is not global nor private to io object, right? What is actualy happening here?

Apo
  • 140
  • 6

1 Answers1

1

You have to read more about closures in javascript. In this specific example, when you boot the application the numClients = 0; is initialized and remains in memory in the execution context of the anonymous function(io). Then, every time that there is a new connection, the io.on('connection') event is triggered, the callback is executed, the numClients is still in the execution context and that's why you will see this var to be incremented.

Stavros Zavrakas
  • 3,045
  • 1
  • 17
  • 30
  • So when the `io.on('connection')` event is triggered, the callback is executed still in the context of `function(io)`? I thought it would be a fresh one, since the setup function was created, executed and forgotten (at least that's what I reasoned). – Apo Oct 07 '16 at 08:57
  • 1
    @Apo this is not the case for node modules. When you require a module, node will cache the module so that if another file will require the module it will return the same instance. This will be helpful: http://stackoverflow.com/questions/9210542/node-js-require-cache-possible-to-invalidate – Stavros Zavrakas Oct 07 '16 at 09:02
  • read more on closures it will help you clear the doubt. It's one the feature which makes JavaScript so powerful and expressive. – Nivesh Oct 07 '16 at 09:59
  • @Svabael - got it. The link you provided was helpful indeed, especially one of the less popular answers by Erik Reppen who described what would be the behavior in closure-less environment. – Apo Oct 07 '16 at 13:46