Socket.io + Express 4

This is my first try of nodejs, I just want to develope a small web application, from frontend to backend. The developing way is not smooth, I write this blog to trace the questions I have met and my own understanding. I hope it will be able to help those who are freshmen of nodejs, just as me.

Strucutre of Express4

The reason why I choose Express 4 is that I created a new Express project in WebStorm and WebStorm uses Express 4 as defult version.

1
2
3
4
5
6
7
8
9
- Project
- bin
- www *www is the startup js file, when project launches, it is called first.*
- node_modules *it saves all dependencies*
- public *static files - image/css/js*
- routes *main logic - controller*
- views *webpage - html/ejs*
- app.js *core configration*
- package.json *dependencies configration and project info*

Install Socket.io

Open your command line, enter the root directory of your project. then use npm to install.

$ npm install –save express@4.15.2

After running above command, we will find there is a folder - socket.io under node_modules, and the dependency is also added automatically.

Is it easy? However, when I first tried, I even didn’t know the correct path to install socket.io.

Realization

Now, Express4 and Socket.io are both ready, let’s combine them to proper functioning.

Back End

We can easily get the sample from the official website of socket.io
https://socket.io/get-started/chat/

var app = require(‘express’)();
var http = require(‘http’).Server(app);
var io = require(‘socket.io’)(http);

app.get(‘/‘, function(req, res){
res.sendFile(__dirname + ‘/index.html’);
});

io.on(‘connection’, function(socket){
console.log(‘a user connected’);
});

http.listen(3000, function(){
console.log(‘listening on *:3000’);
});

This sample creates a socket.io object and pass the http server to it. After server launches, it will listen to 3000 port. When a connection is set up, it will print the log - ‘a user connected’.
Unfortunately, this sample is base on Express 3, all logics are put into a js file(like express module, http server setup, socket.io logic).
And in Express 4, the modules are separated, and combined by module.exports & requir().

  • http module is put in www file.
  • express and most modules are put in app.js file.
  • controller logic are put in index.js file.

www is the startup file, it requires the module form app.js, then app.js requir index.js.

www <- app.js <- index.js
a <- b = a requires b.

I think it will confuse a lot of freshmen, at lest, it confused me.
I simply exported the http server from www, and required it from index.js, finally, it caused a dead loop.
So we must put all logics in one js file? The answer is certainly no.

code

I’ll put my code here, and analyse it later, you can refer to my analysis if you can not understand the code.

in index.js:

1
2
3
4
5
6
7
module.exports = function(io) {
io.on('connection', function(socket) {
console.log('a user connected');
});

return router;
}

in app.js:

1
2
3
4
5
6
7
var socket_io = require('socket.io');

// Socket.io
var io = socket_io();
app.io = io;

var index = require('./routes/index')(io); // remember to remove the original requir() of index.js

in www:

1
2
3
// Socket.io
var io = app.io
io.attach( server );

‘require()’ Modules Execution Sequence

Fristly, I want to analyse the sequence of require() function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
test1.js
console.log("This is test 1.");

function t1() {
console.log("This is a normal function in test 1.");
}
t1();

module.exports = function () {
console.log("This is a export function in test 1.");
}


test2.js
console.log("This is test 2.");
var test1 = require('./test1');

function t2(){
console.log("This is a normal function is test 2.");
}
t2();
test1();

module.exports = function () {
console.log("This is a export function in test 2.");
}


main.js
var test2 = require('./test2');

console.log("This is main.");
test2();


result:
This is test 2.
This is test 1.
This is a normal function in test 1.
This is a normal function in test 2.
This is a export function in test 1.
This is main.
This is a export function in test 2.

From the result, we can find that, the sequence of js is from top to bottom.
When require(‘./test1’) function is executed, it will run the code in test1.js. And pass the function in module.exports, when test1() is called, it runs the export function.

Code Analysis

After understanding the sequence of require(), we can analyse the code easier.
in index.js, it exports the connection function and set the parameter as io(socket.io object).
So where do we get the socket.io? In app.js.
In app.js, it creates the socket.io obeject, and then requires index.js passing the object as parameter. Now, the io.on() is valid.
But it still can not work, because it lacks http server.
There is a function in socket.io, through this function, we can combind the http server with socket.io after initialization. It is - io.attach( server ).
www requires app.js and get socket.io object, finally, attach the http server to socket.io obeject.

The basic configration on server is completed.

Front End

The method to use socket.io in html is easier.
Firstly, add the script element, and set the source as below(this is the relative path of socket.io installed on server).

1
<script src="/socket.io/socket.io.js"></script>

Then, create another js element to realize our logic.
We just need to use a funtion to connect server.

1
var socket = io();

Run the project, and open the url.

1
2
3
{}
GET / 304 23.007 ms - -
a user connected

Succeed!

Reference

socket.io
stackoverflow