简体   繁体   English

在 expressjs 路由中使用 socket.io 而不是在主 server.js 文件中

[英]Use socket.io in expressjs routes instead of in main server.js file

I have express/nodejs api.我有 express/nodejs api。 I am adding socket.io feature to it.我正在向它添加 socket.io 功能。 Currently all of my routes are in separate folders and I include them in server.js file and use them as app.use() function.目前我所有的路由都在单独的文件夹中,我将它们包含在 server.js 文件中并将它们用作 app.use() 函数。

In server.js file, I also start the express server by listening to a particular port such as 3000 as below.在 server.js 文件中,我还通过侦听特定端口(例如 3000)来启动 express 服务器,如下所示。

let server = app.listen(3000);

According to all google searches what I found is that I need to pass server variable to initialize socket.io like following.根据所有谷歌搜索,我发现我需要传递服务器变量来初始化 socket.io,如下所示。

let io = require('socket.io')(server);

Now the question is that since it needs this variable then how can I use socket.io in my routes files which are in different folder to emit and receive events from client?现在的问题是,既然它需要这个变量,那么我如何在不同文件夹中的路由文件中使用 socket.io 来从客户端发出和接收事件?

UPDATE更新

in server.js file在 server.js 文件中

let route = require('./routes/route');

let app = express();

let server = app.listen(3000);

console.log('Listening to port');

let io = require('socket.io')(server);

app.use('/api/1.0/events', route(io));

in route.js file在 route.js 文件中

let express = require('express');

module.exports = (io) => {
    console.log('IO: ', io);
};

UPDATE 2更新 2

server.js file server.js 文件

let express = require('express');
let events = require('./routes/events');
let app = express();
let server = app.listen(3000);

let io = require('socket.io')(server);


app.use(function(request, response, next) {
    request.io = io;
    next();
});

app.use('/events', events);

events.js file events.js 文件

let express = require('express');

let Events = require('../models/events');

apiRoutes.post('/new', function(request, response) {
    let newEvent = new Events(request.body);

    newEvent.save((error, result) => {
        if (error) {
            response.json(error);
        } else {
            // console.log('ELSE');
            // request.io.on('connect', socket => {
                // console.log('LISTENING TO SOCKET...');

                request.io.on('EventCreated', data => {
                    console.log('DATA ON Server: ', data);
                });
            // });

            response.json({
                success: true,
                message: 'New event created'
            });
        }
    });
});

There are multiple ways to share the io variable with route files.有多种方法可以与路由文件共享io变量。

  1. When you require() in your route file, pass it the io variable as a constructor argument.当您在路由文件中使用require()时,将io变量作为构造函数参数传递给它。

  2. Use app.set("io", io) so you can then use let io = app.get("io") in any file that has access to the app object.使用app.set("io", io)这样你就可以在任何可以访问app对象的文件中使用let io = app.get("io")

  3. Create a middleware that puts the io object on every req object so you can access it from there any time.创建一个中间件,将io对象放在每个req对象上,以便您可以随时从那里访问它。


Here's an example of passing it as a constructor argument to the router file:这是将其作为构造函数参数传递给路由器文件的示例:

let server = app.listen(3000);
let io = require('socket.io')(server);

// load other routers
app.use(require("./someRouterFile.js")(io));

// in someRouterFile.js
const express = require('express');

module.exports = function(io) {
    let router = express.Router()

    // define routes
    // io is available in this scope
    router.get(...)

    return router;
}

Here's an example of the app.set() scheme:这是app.set()方案的示例:

let server = app.listen(3000);
let io = require('socket.io')(server);
app.set("io", io);

Then, anywhere in your routes that you have access to the app object, you can get it with:然后,在您可以访问app对象的路线中的任何位置,您都可以通过以下方式获取它:

let io = app.get("io");

Here's an example of using a middleware to set the io object onto every req object so it's available from all routes.这是一个使用中间件将io对象设置到每个req对象上的示例,以便它可以从所有路由中使用。

let server = app.listen(3000);
let io = require('socket.io')(server);

// place this middleware before any other route definitions
// makes io available as req.io in all request handlers
app.use(function(req, res, next) {
    req.io = io;
    next();
});

// then in any express route handler, you can use req.io.emit(...)

Here's an example of using an argument to the module constructor without middleware:这是在没有中间件的情况下使用模块构造函数的参数的示例:

// in mysocket.js
module.exports = (io) => {
    console.log('IO: ', io);
    io.on('connect', socket => {
       // handle various socket connections here
    });

    // put any other code that wants to use the io variable
    // in here


};

Then, in your main file:然后,在您的主文件中:

let server = app.listen(3000);
let io = require('socket.io')(server);

// initialize my socketio module and pass it the io instance
require('./mysocket.js')(io);

In server.js:在 server.js 中:

module.exports.getIO = function(){
     return io;
}

In your route file:在您的路线文件中:

var theServer = require('<path to server.js>');
var iovar = theServer.getIO(); //your io var

Sharing my Solution that I've used分享我使用过的解决方案

Another solution for this problem (that I actually used) is that we can make our io ( socket.io object) object global.这个问题的另一个解决方案(我实际使用过)是我们可以使我们的iosocket.io对象)对象全局化。

Simply assign io to the global.io .只需将io分配给global.io

The io object is in index.js , after creating and setting up the io object simply do global (ie global.io = io; ), now this io object is accessible in any route that we are working within our project. io对象在index.js ,在创建和设置io对象后只需执行global (即global.io = io; ),现在可以在我们在项目中工作的任何路径中访问该io对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM