2012-09-24 17 views
6

estoy tratando de conseguir mi cabeza alrededor ExpressJS y Socket.IO. Tengo mis rutas en un archivo separado que incluyo a mis app.js:ExpressJS - Socket.IO con Ruta Separación

var express = require('express')  
    , db = require('./db') 
    , mongoose = require('mongoose') 
    , models = require('./models/device') 
    , http = require('http') 
    , path = require('path') 
    , app = express() 
    , server = http.createServer(app) 
    , io = require('socket.io').listen(server) 
    , routes = require('./routes/myRoutes'); 

Sin embargo cuando intento y emitirá un evento de una de mis rutas tengo ninguna referencia a Socket.IO.

exports.update = function(req, res){ 
    return Item.findById(req.params.id, function(err, item) { 
     // Do some checks and save. 
     socket.emit('updated'); 
    } 
} 

Entiendo por qué esto podría no estar disponible. Por el contrario, no entiendo cuál es la mejor forma de obtener un control sobre socket.io de otro archivo que no sea app.js. Miraba this question (vea la respuesta de Ricardo) pero aún no estoy seguro. Idealmente me gustaría evitar hacer esto:

rutas = requiere ("rutas/MyRoutes") (IO);

+0

puede evitar el uso del módulo http, aunque socket.io necesita un servidor http, puede llamarlo desde la dependencia expresa (3.xx) así: var app = express(), server = app.listen (3000), io = socket.listen (servidor); –

+0

Actualización: Eche un vistazo a feathers.js – backdesk

Respuesta

5

Salida express.io

Tiene enrutamiento de solicitudes en tiempo real, y un montón de otras características útiles.

app = require('express.io')() 
app.http().io() 

app.io.route('example', function(req) { 
    // do something interesting 
})) 

app.listen(7076) 

En cuanto a conseguir alrededor de tener que pasar el objeto io alrededor. Tiene algunas opciones, que pueden ser o no las "mejores" según a quién le pregunte.

  • Marca io o app global. (Algunas personas se asustan más globales)
  • Uso module.exports y require el objeto en el otro archivo. (Puede llevar a problemas de dependencia circular, si no se hace correctamente)

pasando el objeto io es probablemente la forma más sencilla más limpio, pero usted tiene opciones.

+1

Enlace muerto. ¿Depreceated? – Keith

+0

express.io link dead, está redirigiendo a express-io.org –

2

socket.io no funciona con rutas, funciona con tomas.

Se agrega este código para app.js o un archivo separado que se incluye en app.js:

io.sockets.on('connection', function (socket) { 
    socket.on('update', function (your_id) { 
    Item.findById(your_id, function(err, item) { 
     socket.emit('send_update', item); 
    } 
    }); 
}); 

La ruta de actualización sólo sirve para hacer un documento HTML con Javascript, que contiene:

<script src="/socket.io/socket.io.js"></script> 
<script> 
    var socket = io.connect('http://localhost'); 
    socket.emit('update', { your_id: '1' }); 
    socket.on('send_update', function (data) { 
    console.log(data); 
    }); 
</script> 

Así que una vez que la página se procesa y completa, el cliente-javascript abrirá un socket al servidor y recibirá datos adicionales.

Ver more examples here.

de responsabilidad: Código escrito desde cero y no probado.

+0

Entendido. Mi aplicación exprés solo actúa como una API relajante, por lo que no hay mucho más allá de la vista que no sea la predeterminada. Quería emitir un evento una vez que el registro había cambiado, simplemente no estaba seguro de si debía enviar la notificación desde el servidor (una vez que se guardó) o el cliente. – backdesk

+0

Puedes hacer eso con .post-route en express y en [jQuery] (http://api.jquery.com/change/)/[ajax] (http://api.jquery.com/jQuery.post /) solución. Podría ser mejor que socket.io. – Patrick

2

La mejor manera es utilizar el cierre. Ej:

exports.update = function(socket){ 
    return function(req, res) { 
    //In here now you can have the reference to the socket io 
    Item.findById(req.params.id, function(err, item) { 
     // Do some checks and save. 
     socket.emit('updated'); 
    } 
    } 
} 

Y:

app.post('/your_path', update(io)); 
9

Bueno, realmente no necesita express.io para eso. La solución más fácil sería exportar un nuevo módulo y pasarle una referencia a la instancia de socket.io. Entonces en tu aplicación.js tiene:

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

ahora requieren un nuevo módulo y lo pasan la referencia socketio. Añadir esta nueva línea (en app.js) para hacerlo:

require('./app/path/to/your/socketio/controller/socketio')(io); 

A continuación, cree un nuevo archivo en sus path/to/your/socketio/controller llamados socketio.js

Y finalmente en el archivo socketio.js, exportar su nuevo módulo :

module.exports = function(io) { 

    io.sockets.on('connection', function (socket) { 

     socket.on('captain', function(data) { 

      console.log(data); 

      socket.emit('america'); 
     }); 
    }); 
}; 

¡Y listo!

+0

Gracias por el ejemplo. ¿Podría dar más detalles sobre no necesitar expresar? He estado pensando durante un tiempo sobre formas de implementar una solución pura basada en socket. – backdesk

+2

Esta estrategia de módulo "sockets.js" parece bastante popular en Github, pero por mi vida, no puedo entender cómo el archivo de rutas (por ejemplo,/rutas/mis Rutas) tendrá acceso a ese módulo (sockets.js) más adelante. :( –

0

He utilizado el enrutador middleware de Expressjs (estoy usando 4.x).

En el archivo de ruta externa pongo el "próximo" objeto:

module.exports = function(app, settings){ 
    app.post('/something', function(req, res, next) { 
    ... 
    next(); 
    } 
}; 

Y en el archivo principal escribo la última ruta de salto dentro de la io.on ('conexión'):

io.on('connection', function (socket) { 

    // Final route for middlewares who need to interact with socket.io 
    app.post('/something', function (req, res, next) { 
     socket.emit('event', { result: 'ok' }); 
    }); 

});