express.js 4和带express路由器的插座

express.js 4和带express路由器的插座,express,socket.io,Express,Socket.io,我正在尝试使用express.js 4创建一个非常简单的节点API,但是我需要一些“实时”事件,我为这些事件添加了socket.io。我对这两个方面都比较陌生,所以我可能缺少一些基本的东西,但我找不到关于这方面的好的文档/教程 在express应用程序(使用express generator创建)中,基于我阅读的简单示例和项目文档,我有类似的内容。这可以正常工作,通过客户端应用程序,我可以发送/接收套接字事件: var express = require('express'); var path

我正在尝试使用express.js 4创建一个非常简单的节点API,但是我需要一些“实时”事件,我为这些事件添加了socket.io。我对这两个方面都比较陌生,所以我可能缺少一些基本的东西,但我找不到关于这方面的好的文档/教程

在express应用程序(使用express generator创建)中,基于我阅读的简单示例和项目文档,我有类似的内容。这可以正常工作,通过客户端应用程序,我可以发送/接收套接字事件:

var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));

app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api', api);

io.sockets.on('connection', function (socket) {
    console.log('client connect');
    socket.on('echo', function (data) {
        io.sockets.emit('message', data);
    });
});


// error handlers omitted

module.exports = app;
但是我想使用API路由中的套接字(在上面我“需要”的./routes/API.js文件中)。例如,有人可能使用API放置/发布资源,我希望广播到连接的socket.io客户端

我看不到如何在express routes中使用'io'变量或组织当前
io.sockets.on('connection')…
函数中的代码。以下是
/routes/api.js
文件:

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

router.put('/foo', function(req, res) {
    /* 
      do stuff to update the foo resource 
      ...
     */

    // now broadcast the updated foo..
    io.sockets.emit('update', foo); // how?
});

module.exports = router;

我对你的文件做了一点修改,你能检查一下它是否有效吗

您可以将您定义的io传递给您的路由,如下所示

require('./routes/api')(app,io); 
我没有测试Socket.IO部分,但没有语法错误,路由也正常工作

server.js文件:

var express = require('express');
var app = express();
var path = require('path');
var logger = require('morgan');

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

app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));

io.sockets.on('connection', function (socket) {
    console.log('client connect');
    socket.on('echo', function (data) {
    io.sockets.emit('message', data);
 });
});

require('./routes/api')(app,io); 

console.log("Server listening at port 3000");
api.js:

module.exports = function(app,io) {
app.put('/foo', function(req, res) {

    /* 

      do stuff to update the foo resource 

      ...

     */


    // now broadcast the updated foo..

    console.log("PUT OK!");

    io.sockets.emit('update'); // how?
    res.json({result: "update sent over IO"});

});
}

一个选项是将其传递给req对象

app.js:

var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));

app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));

io.sockets.on('connection', function (socket) {
    console.log('client connect');
    socket.on('echo', function (data) {
        io.sockets.emit('message', data);
    });
});

// Make io accessible to our router
app.use(function(req,res,next){
    req.io = io;
    next();
});

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

// error handlers omitted

module.exports = app;
./routes/api.js:

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

router.put('/foo', function(req, res) {
    /* 
      do stuff to update the foo resource 
      ...
     */

    // now broadcast the updated foo..
    req.io.sockets.emit('update', foo); 
});

module.exports = router;

假设您想从应用程序中的任何位置(而不仅仅是路由器)访问SocketIO,您可以为它创建一个单例。这对我来说是可行的:

//socket-singletion.js
var socket=require('socket.io');
var SocketSingleton=(函数(){
this.io=null;
this.configure=函数(服务器){
this.io=套接字(服务器);
}
归还这个;
})();
module.exports=SocketSingleton;
然后,您需要使用服务器对其进行配置:

//服务器配置文件
var SocketSingleton=require('./SocketSingleton');
var http=require('http');
var server=http.createServer(app);
SocketSingleton.configure(server);//还有一个选项要使用

app.js 路由/api.js
我认为最好的方法是将io设置为req的属性,如下所示:

app.use(function(req,res,next){
    req.io = io;
    next();
});

app.use('/your-sub-link', your-router);

谢谢Caner。这很有效,我可以使用它,因为这个特定的应用程序相当简单。但是当我试图使用它来学习一些最佳实践时,有没有办法继续使用express Router()呢?这似乎是express 4.x的惯用方式。@darrend,根据express.js文档,看起来这样使用是可以的,你认为呢?这是合理的-我会标记为已接受,并深入研究文档和代码。感谢帮助。为大家更新:我找到了一个更干净的解决方案Logan Tegman Hey@cdagli,I tr我试过了。但是它说,
错误:听着EADDRINUSE:::3000
。你真的让上面的代码工作了吗?我请求的io在我的路由器代码中一直显示为未定义。我在那里犯了一个错误-部分
//让我们的路由器可以访问io
应该在
应用程序使用('/api',api)之前定义;
在您的解决方案中,socket-singletion.js中的这个关键字在初始化时仍然没有定义。@abhishake您使用的是箭头函数吗?如果是,则“this”的行为会有所不同,并且可能不会像上面描述的那样工作
const express = require('express');
const router = express.Router();

router.put('/foo', function(req, res) {
    /*
     * API
     */

    // Broadcast the updated foo..
    req.app.io.sockets.emit('update', foo);
});

module.exports = router;
app.use(function(req,res,next){
    req.io = io;
    next();
});

app.use('/your-sub-link', your-router);