express.js 4和带快速路由器的套接字

时间:2015-03-29 21:03:08

标签: express socket.io

我正在尝试使用express.js 4创建一个非常简单的节点API,但我需要一些'实时'事件,我添加了socket.io。我对两者都很新,所以我可能会遗漏一些基本的东西,但我找不到好的文档/ tuts。

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

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​​来PUT / POST资源,我希望该广播连接到socket.io客户端。

我看不到如何使用'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;

5 个答案:

答案 0 :(得分:24)

一种选择是将其传递给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;

./路由/ 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;

答案 1 :(得分:14)

我已经修改过你的文件了,你可以检查它是否有效吗?

您可以将已定义的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"});

});
}

答案 2 :(得分:1)

假设您想从应用程序中的任何地方访问SocketIO,而不仅仅是在路由器中,都可以为其创建一个单例。这对我有用:

//socket-singletion.js

var socket = require('socket.io');

var SocketSingleton = (function() {
  this.io = null;
  this.configure = function(server) {
    this.io = socket(server);
  }

  return this;
})();

module.exports = SocketSingleton;

然后,您需要使用服务器进行配置:

//server config file

var SocketSingleton = require('./socket-singleton');
var http = require('http');
var server = http.createServer(app);
SocketSingleton.configure(server); // <--here
server.listen('3000');

最后,在任何需要的地方使用它:

//router/index.js

var express = require('express');
var router = express.Router();
var SocketSingleton = require('../socket-singleton');

/* GET home page. */
router.get('/', function(req, res, next) {
  setTimeout(function(){
    SocketSingleton.io.emit('news', {msg: 'success!'});
  }, 3000);
  res.render('index', { title: 'Express' });
});

module.exports = router;

答案 3 :(得分:0)

另一种选择是使用a thread in the npm community forum.

app.js

const express = require('express');
const path = require('path');
const logger = require('morgan');
const api = require('./routes/api');

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

// Keep the io instance
app.io = io;

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

// ...

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

module.exports = app;

routes / api.js

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;

答案 4 :(得分:0)

我认为最好的方法是将io设置为req的属性,如下所示:

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

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