Usando socket.io en Express 4 y express-generator's / bin / www

93

Así que aquí está el trato: estoy tratando de usar socket.io en un proyecto express. Después de que se lanzó Express Js 4, actualicé mi generador expreso y ahora las funciones iniciales de la aplicación entran en el ./bin/wwwarchivo, incluidas esas vars (contenido del archivo www: http://jsfiddle.net/avMa5/ )

var server = app.listen(app.get('port'), function() {..}

(compruébalo npm install -g express-generatory luegoexpress myApp

Dicho esto, recordemos cómo los documentos de socket.io nos piden que lo disparemos:

var app = require('express').createServer();
var io = require('socket.io')(app);

Ok, pero no puedo hacerlo dentro de app.js, como se recomienda. Esto debe hacerse en ./bin/www para que funcione. en ./bin/www esto es lo que puedo hacer para que funcione:

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

Ok, esto funciona, pero no puedo usar la var io en ningún otro lugar, y realmente no quiero poner mis funciones socket.io en el wwwarchivo.

Supongo que esta es solo una sintaxis básica, pero no puedo hacer que esto funcione, ni siquiera usando module.exports = servero server.exports = serverni module.exports.io = app(io)en el archivo www.

Entonces, la pregunta es: ¿cómo puedo usar socket.io con este archivo / bin / www como punto de partida de mi aplicación?

usuario1576978
fuente
No tiene que poner la importación ./bin/www.. Solo ponlo en el mismo lugar, donde var appestá tu .
alandarev
15
Ojalá la gente dejara de sugerir express-io. Está desactualizado y ya no se mantiene.
Ben Fortune
@Mritunjay gracias, pero no lo resolvió: /
user1576978
@BenFortune lo siento, lo tendré en cuenta.
Mritunjay
@alandarev var app = express () ?? De hecho lo probé, sin éxito
user1576978

Respuestas:

160

Tengo una solución para hacer que socket.io esté disponible en app.js.

app.js:

var express      = require( "express"   );
var socket_io    = require( "socket.io" );

// Express
var app          = express();

// Socket.io
var io           = socket_io();
app.io           = io;

(...)

// socket.io events
io.on( "connection", function( socket )
{
    console.log( "A user connected" );
});

module.exports = app;

// Or a shorter version of previous lines:
//
//    var app = require( "express"   )();
//    var io  = app.io = require( "socket.io" )();
//    io.on( "connection", function( socket ) {
//        console.log( "A user connected" );
//    });
//    module.exports = app;

bin / www:

(...)

/**
 * Create HTTP server.
 */

var server = http.createServer( app );


/**
 * Socket.io
 */

var io     = app.io
io.attach( server );

(...)

De esta manera, puede acceder a la variable io en su app.js, e incluso ponerla a disposición de sus rutas definiendo module.exports como una función que acepta io como parámetro.

index.js

module.exports = function(io) {
    var app = require('express');
    var router = app.Router();

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

    return router;
}

Luego, pase io al módulo después de que esté configurado:

app.js

// Socket.io
var io = socket_io();
app.io = io;

var routes = require('./routes/index')(io);
Gabriel Hautclocq
fuente
1
Soy nuevo en NodeJS. ¿Puede explicar qué está sucediendo exactamente en esta línea app.io = io;en el app.jsarchivo
Aryak Sengupta
3
Es simplemente una cuestión de poner la variable io en el objeto de la aplicación. También podría ser: app.io = socket_io ();
Gabriel Hautclocq
7
"... e incluso ponerlo a disposición de tus rutas si quieres". Vale, pero ¿cómo? Sería genial si pudiera dar un ejemplo de cómo hacerlo.
scaryguy
2
¿No es malo adjuntar una propiedad personalizada al appobjeto? Mejor use símbolos o app.set().
Alexander Gonchiy
3
¿Por qué app.io = iocuando podría usar module.exports = { app, io }en su lugar?
Manan Mehta
56

Un enfoque un poco diferente para iniciar socket.io, agrupa todo el código relacionado en un solo lugar:

bin / www

/**
 * Socket.io
 */
var socketApi = require('../socketApi');
var io = socketApi.io;
io.attach(server);

socketApi.js

var socket_io = require('socket.io');
var io = socket_io();
var socketApi = {};

socketApi.io = io;

io.on('connection', function(socket){
    console.log('A user connected');
});

socketApi.sendNotification = function() {
    io.sockets.emit('hello', {msg: 'Hello World!'});
}

module.exports = socketApi;

app.js

// Nothing here

De esta manera, socket.iopuedo invocar todo el código relacionado en un módulo y su función desde cualquier lugar de la aplicación.

Anatoly
fuente
4
¡Esta respuesta merece más votos a favor! Muy simple y limpio, mantiene las rutas de socket fuera de www , app.js y también fuera de index.js (sí, fuera de index.js ), este archivo solo debe contener rutas HTTP Express.
adelriosantiago
1
Increíble, muy limpio
sanket
3
¿Alguien puede actualizar esto para socket.io 2.0? No está funcionando para mi. io.attach (servidor) y io.listen (servidor) arrojan "no se puede leer la propiedad X de indefinido".
tsujp
1
También para hablar con @tsujp la mía funciona igual. Tienes que presionar la URL correcta y agregar el cliente socket.io y verás que funciona
Tamb
Tengo un problema similar al de @tsujp, estoy usando socket.io 2.3.0 y io.attach is not a function
obtengo
43

Resulta que realmente fue un problema básico de sintaxis ... Obtuve estas líneas de este tutorial de chat de socket.io ...

en ./bin/www, justo después var server = app.listen(.....)

var io = require('socket.io').listen(server);
require('../sockets/base')(io);

así que ahora creo el archivo ../sockets/base.js y pongo este pequeño dentro de él:

module.exports = function (io) { // io stuff here... io.on('conection..... }

¡Si! Ahora funciona ... Así que supongo que realmente no tenía otra opción que iniciar socket.io dentro de / bin / www, porque ahí es donde se inició mi servidor http. El objetivo es que ahora pueda construir la funcionalidad de socket en otro (s) archivo (s), manteniendo la cosa modular, porrequire('fileHere')(io);

<3

usuario1576978
fuente
1
El problema es que no puedes hacer algo comoio.on('connection', function(socket) { res.render('connection.jade') });
Gofilord
3
@Gofilord, eso se debe a que anula todo el propósito de los sockets ... lo que necesita es un enrutamiento regular que incluya renderizado. Los sockets están aquí para enviar mensajes entre el cliente y el servidor sin solicitudes http. tal vez lea este artículo enterprisewebbook.com/ch8_websockets.html
Unispaw
19

El antiguo "expressjs", todo sucede en el archivo "app.js". Entonces, el enlace de socket.io al servidor también ocurre en ese archivo. (Por cierto, todavía se puede hacerlo a la antigua y eliminar bin / www)

Ahora, con el nuevo expressjs, debe suceder en el archivo "bin / www".

Afortunadamente, javascript / requirejs facilitó el paso de objetos. Como señaló Gabriel Hautclocq, socket.io todavía se "importa" en "app.js" y se adjunta al objeto "app" a través de una propiedad

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

El socket.io se activa adjuntando el servidor en "bin / www"

app.io.attach(server); 

porque el objeto "app" se pasó a "bin / www" anteriormente

app = require("../app");

Es realmente tan simple como

require('socket.io')().attach(server);

Pero hacerlo de la manera "difícil" asegura que app.ioahora contenga el objeto socke.io.

Ahora, si necesita este objeto socket.io también en "rutas / index.js", por ejemplo, simplemente use el mismo principio para pasar ese objeto.

Primero en "app.js", haz

app.use('/', require('./routes/index')(app.io));

Luego, en "rutas / index.js"

module.exports = function(io){
    //now you can use io.emit() in this file

    var router = express.Router();



    return router;
 }

Entonces "io" se inyecta en "index.js".

Zhe Hu
fuente
9

Actualización de la respuesta de Gabriel Hautclocq :

En el archivo www, el código debería aparecer como el siguiente debido a las actualizaciones con Socket.io. Attach ahora es Escuchar.

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);


/**
 * Socket.io
 */
var io = app.io;
io.listen(server);`

Además, para que esa conexión funcione también es necesario implementar la API del lado del cliente. Esto no es específico de Express, pero sin él, la llamada de conexión no funcionará. La API está incluida en

/node_modules/socket.io-client/socket.io.js. 

Incluya este archivo en la interfaz y pruebe con lo siguiente:

var socket = io.connect('http://localhost:3000');
rickrizzo
fuente
7

Después de leer todos los comentarios, se me ocurrió lo siguiente usando la versión del servidor Socket.io: 1.5.0

Problemas con los que me encontré:

  1. var sockIO = require ('socket.io') debería ser var sockIO = require ('socket.io') () . (Crédito a: Zhe Hu )

  2. sockIO.attach debe ser sockIO. escuchar (Crédito a: rickrizzo )

Pasos

  1. Instale Socket.io con el siguiente comando:

    npm install --save socket.io
  2. Agregue lo siguiente a app.js :

    var sockIO = require('socket.io')();
    app.sockIO = sockIO;
  3. En bin / www , después de var server = http.createServer (app) , agregue lo siguiente:

    var sockIO = app.sockIO;
    sockIO.listen(server);
  4. Para probar la funcionalidad, en app.js , puede agregar la línea:

    sockIO.on('connection', function(socket){
        console.log('A client connection occurred!');
    });
Brian
fuente
5

Un tutorial para principiantes de Cedric Pabst
aquí son los conceptos básicos breves del enlace para un chat de aplicación:

usando express-generate y el motor ejs utilizable en cada enrutamiento estándar de archivos .ejs en express-generate

edite el archivo bin \ www y agregue este app.io.attach (servidor); Me gusta esto

...
/*
 * Create HTTP server.
/*  
var server = http.createServer(app);
/*
 * attach socket.io
/*  
app.io.attach(server); 
/*
 * Listen to provided port, on all network interfaces.
/*  
...

editar en app.js

//connect socket.io
... var app = express();
// call socket.io to the app
app.io = require('socket.io')();

//view engine setup
app.set('views', path.join(_dirname, 'views'));
...



...
//start listen with socket.io
app.io.on('connection', function(socket){
console.log('a user connected');

// receive from client (index.ejs) with socket.on
socket.on('new message', function(msg){
      console.log('new message: ' + msg);
      // send to client (index.ejs) with app.io.emit
      // here it reacts direct after receiving a message from the client
      app.io.emit('chat message' , msg);
      });
});
...
module.exports = app;

editar en index.ejs

 <head>  
   <title><%= title %></title>
   <link rel='stylesheet' href='/stylesheets/style.css' />
   <script src="/socket.io/socket.io.js"></script>
   //include jquery
   <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
   <script>
   var socket = io();
   //define functions socket.emit sending to server (app.js) and socket.on receiving 
     // 'new message' is for the id of the socket and $('#new-message') is for the button
     function sendFunction() {
     socket.emit('new message', $('#new-message').val());
     $('#new-message').val('');
   }
    // 'chat message' is for the id of the socket and $('#new-area') is for the text area
   socket.on('chat message', function(msg){
     $('#messages-area').append($('<li>').text(msg));
   });
   </script>
 </head>  

 <body>  
   <h1><%= title %></h1>
   <h3>Welcome to <%= title %></h3>
   <ul id="messages-area"></ul>
   <form id="form" onsubmit="return false;">
     <input id="new-message" type="text" /><button onclick="sendFunction()">Send</button>
   </form>
 </body>

Diviértete :) y muchas gracias a Cedric Pabst

AnnaBanana
fuente
2

Algunas respuestas anteriores no funcionan y otras son demasiado complicadas. En su lugar, pruebe la siguiente solución ...

Instale los módulos de nodo socket.io del lado del servidor y del lado del cliente:

npm install --save socket.io socket.io-client

Lado del servidor

Agregue el siguiente código a bin / www después de la definición del servidor var server = http.createServer(app);:

/**
 * Socket.io
 */

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

io.on("connection", function(socket){
  console.log("SOCKET SERVER CONNECTION");
  socket.emit('news', { hello: 'world' });
});

Lado del cliente

Si usa webpack, agregue el siguiente código a su archivo webpack entry.js :

var socket = require('socket.io-client')();
socket.on('connect', function(){
  console.log("SOCKET CLIENT CONNECT")
});

socket.on('news', function(data){
  console.log("SOCKET CLIENT NEWS", data)
});

Hecho. Visite su sitio y compruebe la consola de desarrollador js del navegador.

s2t2
fuente