使用Express 4模块化Socket.io

时间:2022-08-22 15:48:44

I'm trying to modularize my application files and I'm having problems with Socket.io. I would like to use the io inside my routes.js. Something like this:

我正在尝试模块化我的应用程序文件,我遇到了Socket.io的问题。我想在我的routes.js中使用io。像这样的东西:

var router = require('express').Router();
var io     = require('./sockets/my-io');

router.get('/', function(req, res) {
  io.emit('request-detected');
});

module.exports = router;

But I can't do, because the socket.io needs the app server, and when I'm inside the routes.js file, the app server is not listening or being exported yet.

但是我不能这样做,因为socket.io需要app服务器,而当我在routes.js文件中时,app服务器还没有监听或导出。

Can you give me a solution, or any other approach to this problem?

你能给我一个解决方案,或任何其他方法来解决这个问题吗?

Here's what I have, and if it's possible, I would like to keep the file structure:

这就是我所拥有的,如果可能的话,我想保留文件结构:

app.js

var app = require('express')();
var routes = require('./routes');

/* ... */

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

module.exports = app;

bin/www

#!/usr/bin/env node

var app = require('../wallet');

var server = app.listen(port, function() {
  debug('Express is listening o port ' + port);
});

routes.js

var router = require('express').Router();

router.get('/', function(req, res) {
  console.log('hey');
});

module.exports = router;

2 个解决方案

#1


2  

You can do it by passing the io variable to your routes module.

您可以通过将io变量传递给路由模块来完成此操作。

bin/www

#!/usr/bin/env node

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

var server = app.listen(3000, function() {
    console.log('Express is listening on port 3000');
}); // start the server

var socket = require('./socket')(server); // require socket.io code
var routes = require('./routes')(socket); // require routes

app.use('/', routes);

app.js

var express = require('express');

var app = express();

app.use(express.static(__dirname + '/public'));
app.set('views engine', 'ejs');
app.set('views', __dirname + '/');

module.exports = app;

socket.js

var socketio = require('socket.io');
function init(server) {
    var io = socketio(server);
    io.on('connection', function (socket) {
        console.log("socket connected");
        socket.on('newEvent', function (data) {
            console.log(data);
        });
    });
    return io;
}

module.exports = init;

routes.js

var express = require('express');
var route = express.Router();

function init(io) {
    route.get('/', function (req, res) {
        res.render('index.ejs', {});
        setTimeout(function() {io.emit('newEvent', {message: "Hi from the server"})}, 2000);
    });
    return route;
}
module.exports = init;

The code above worked for me. However, I'm not sure why you want to do that.

上面的代码对我有用。但是,我不确定你为什么要这样做。

Inside the router, you still have full control of what you want to send to the user via html, so you can just add the data to the html directly. The idea of socket.io is that you can send data between the client and back once he has loaded the html and established a connection to your server with socket.io.

在路由器内部,您仍然可以通过html完全控制要发送给用户的内容,因此您可以直接将数据添加到html中。 socket.io的想法是,一旦他加载了html并使用socket.io建立了与服务器的连接,就可以在客户端和后端之间发送数据。

As you can see in the routes.js, I had to add a timeout to the emit. This is because the socket event will be emit before the browser has reloaded the page. In my case the browser logged the event and then immediately refreshed, losing the data you just sent.

正如您在routes.js中看到的,我不得不向emit添加超时。这是因为套接字事件将在浏览器重新加载页面之前发出。在我的情况下,浏览器记录了事件,然后立即刷新,丢失了刚刚发送的数据。

Another problem is that you don't know anything about the socket of the client that is requesting the page because he hasn't connected yet. This means that calling io.emit() will send the event to all connected sockets.

另一个问题是你对请求页面的客户端的套接字一无所知,因为他还没有连接。这意味着调用io.emit()会将事件发送到所有连接的套接字。

As I said, this really depends on what exactly you want to do.

正如我所说,这实际上取决于你想要做什么。

EDIT:

Instead of updating your contacts using ajax, you can do that with socket.io.

您可以使用socket.io执行此操作,而不是使用ajax更新联系人。

socket.js

var socketio = require('socket.io');
function init(server) {
    var io = socketio(server);
    io.on('connection', function (socket) {
        console.log("socket connected");
        socket.on('newContact', function (data, callback) {
            // add data.contactName to db

            // after adding something, you use the callback to
            // send the added data back to the client

            // callback(newContact);
        });
    });
    return io;
}

module.exports = init;

index.html

<script type="text/javascript" >
    var socket = io();
    // call this emit when the user wants to add a contact
    socket.emit('newContact', {contactName: name}, function(newContact) {
        // here you will get the result from the server and you can
        // update the html with jquery for example
    });
</script>

#2


0  

If i understand your question correctly ,maybe you can try this way.

如果我正确理解你的问题,也许你可以尝试这种方式。

in your routes.js file

在routes.js文件中

var app    = require('./app');
var server = require('http').createServer(app);
var io     = require('./sockets/my-io')(server);
var route  = app.Router();

in your app.js file

在你的app.js文件中

var port = process.env.PORT || 3000;

app.listen(port,function(){ 
    console.log('server on port ' + port)
})

#1


2  

You can do it by passing the io variable to your routes module.

您可以通过将io变量传递给路由模块来完成此操作。

bin/www

#!/usr/bin/env node

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

var server = app.listen(3000, function() {
    console.log('Express is listening on port 3000');
}); // start the server

var socket = require('./socket')(server); // require socket.io code
var routes = require('./routes')(socket); // require routes

app.use('/', routes);

app.js

var express = require('express');

var app = express();

app.use(express.static(__dirname + '/public'));
app.set('views engine', 'ejs');
app.set('views', __dirname + '/');

module.exports = app;

socket.js

var socketio = require('socket.io');
function init(server) {
    var io = socketio(server);
    io.on('connection', function (socket) {
        console.log("socket connected");
        socket.on('newEvent', function (data) {
            console.log(data);
        });
    });
    return io;
}

module.exports = init;

routes.js

var express = require('express');
var route = express.Router();

function init(io) {
    route.get('/', function (req, res) {
        res.render('index.ejs', {});
        setTimeout(function() {io.emit('newEvent', {message: "Hi from the server"})}, 2000);
    });
    return route;
}
module.exports = init;

The code above worked for me. However, I'm not sure why you want to do that.

上面的代码对我有用。但是,我不确定你为什么要这样做。

Inside the router, you still have full control of what you want to send to the user via html, so you can just add the data to the html directly. The idea of socket.io is that you can send data between the client and back once he has loaded the html and established a connection to your server with socket.io.

在路由器内部,您仍然可以通过html完全控制要发送给用户的内容,因此您可以直接将数据添加到html中。 socket.io的想法是,一旦他加载了html并使用socket.io建立了与服务器的连接,就可以在客户端和后端之间发送数据。

As you can see in the routes.js, I had to add a timeout to the emit. This is because the socket event will be emit before the browser has reloaded the page. In my case the browser logged the event and then immediately refreshed, losing the data you just sent.

正如您在routes.js中看到的,我不得不向emit添加超时。这是因为套接字事件将在浏览器重新加载页面之前发出。在我的情况下,浏览器记录了事件,然后立即刷新,丢失了刚刚发送的数据。

Another problem is that you don't know anything about the socket of the client that is requesting the page because he hasn't connected yet. This means that calling io.emit() will send the event to all connected sockets.

另一个问题是你对请求页面的客户端的套接字一无所知,因为他还没有连接。这意味着调用io.emit()会将事件发送到所有连接的套接字。

As I said, this really depends on what exactly you want to do.

正如我所说,这实际上取决于你想要做什么。

EDIT:

Instead of updating your contacts using ajax, you can do that with socket.io.

您可以使用socket.io执行此操作,而不是使用ajax更新联系人。

socket.js

var socketio = require('socket.io');
function init(server) {
    var io = socketio(server);
    io.on('connection', function (socket) {
        console.log("socket connected");
        socket.on('newContact', function (data, callback) {
            // add data.contactName to db

            // after adding something, you use the callback to
            // send the added data back to the client

            // callback(newContact);
        });
    });
    return io;
}

module.exports = init;

index.html

<script type="text/javascript" >
    var socket = io();
    // call this emit when the user wants to add a contact
    socket.emit('newContact', {contactName: name}, function(newContact) {
        // here you will get the result from the server and you can
        // update the html with jquery for example
    });
</script>

#2


0  

If i understand your question correctly ,maybe you can try this way.

如果我正确理解你的问题,也许你可以尝试这种方式。

in your routes.js file

在routes.js文件中

var app    = require('./app');
var server = require('http').createServer(app);
var io     = require('./sockets/my-io')(server);
var route  = app.Router();

in your app.js file

在你的app.js文件中

var port = process.env.PORT || 3000;

app.listen(port,function(){ 
    console.log('server on port ' + port)
})