Using Socket.io in Express.js Project

2019-01-19 10:01发布

问题:

I'm making some single page web application with Node.js, Express and Socket.io. I want to display how works are going to browser. In IDE, There is console, so I can check program process in console window. Like, I want to show these process to browser. All I want to is just 'emit'.

When I use socket.io in app.js file, there is no problem. but this is limited for me. I want to display many sentences in realtime as running. How can I use socket.io in not only app.js but controller.js? I red Use socket.io in controllers this article, but I can't understand. Please help me with a simple solution.

app.js

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

module.exports.io = io;
...

controller.js

var io = require('./app').io;
// some task
console.log('Task is done!'); // it would be seen in console window
io.sockets.emit('Task is done!'); // Also I want to display it to broswer

Result (error)

TypeError: Cannot read property 'sockets' of undefined

Edit 2---

Follwoing Ashley B's comments, I coded like this.

controller.js

module.exports.respond = function(socket_io) {
    socket_io.emit('news', 'This is message from controller');
 };

app.js

var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var controller = require('./controller');
io.sockets.on('connection', controller.respond );

It works well, But what I wonder is... When I want to several socket_emit, What Should I do? Should I call everytime? If you don't understand. see below :

//first task is done 
module.exports.respond = function(socket_io) {
    socket_io.emit('news', 'First task is done!');
 };

//second task is done 
module.exports.respond = function(socket_io) {
    socket_io.emit('news', 'Second task is done!');
 };

//third task is done 
module.exports.respond = function(socket_io) {
    socket_io.emit('news', 'Third task is done!');
 };

But It is wrong way, right? only last api is implemented in app.js. There are a lot of console.log in my controller, I want to convert it to socket.emit How can I do this?

回答1:

I have worked on this using socket.io and nodejs events. The idea is to handle the emission of the socket only from the app.js, and emit nodejs events from controllers, which will be captured in app.js and then issued by the socket.

app.js

const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server);
const events = require('events');

io.on('connection', function(socket) {
    console.log("Someone has connected");
    var eventEmitter = new events.EventEmitter();
    eventEmitter.on("newEvent", (msg) => { // occurs when an event is thrown
        socket.emit("news", msg);
    });

    exports.emitter = eventEmitter; // to use the same instance
});

myController.js

const app = require('../app');    
.....

if (app.emitter) // Checking that the event is being received, it is only received if there is someone connected to the socket
    app.emitter.emit("newEvent", "First task is done!");    
.....

if (app.emitter)
    app.emitter.emit("newEvent", "Second task is done!");