Utilisation de socket.io dans Express 4 et express-Generator / bin / www

93

Voici donc le problème: j'essaye d'utiliser socket.io dans un projet express. Après le lancement d'Express Js 4, j'ai mis à jour mon générateur express et maintenant les fonctions initiales de l'application vont dans le ./bin/wwwfichier, y compris ces vars (contenu du fichier www: http://jsfiddle.net/avMa5/ )

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

(vérifiez-le d'ici npm install -g express-generatoret ensuiteexpress myApp

Cela étant dit, rappelons-nous comment la documentation socket.io nous demande de le déclencher:

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

Ok mais je ne peux pas le faire dans app.js, comme recommandé. Cela devrait être fait dans ./bin/www pour fonctionner. dans ./bin/www voici ce que je peux faire pour le faire fonctionner:

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

Ok cela fonctionne, mais je ne peux pas utiliser le var io ailleurs, et je ne veux vraiment pas mettre mes fonctions socket.io dans un wwwfichier.

Je suppose que ce n'est qu'une syntaxe de base, mais je ne peux pas faire fonctionner cela, même pas en utilisant module.exports = serverou server.exports = serverni module.exports.io = app(io)sur le fichier www

La question est donc: comment puis-je utiliser socket.io en ayant ce fichier / bin / www comme point de départ de mon application?

utilisateur1576978
la source
Vous n'avez pas besoin de mettre l'importation ./bin/www.. Mettez-le simplement au même endroit, là où vous var appêtes.
alandarev
15
J'aimerais que les gens arrêtent de suggérer express-io. Il est obsolète et n'est plus entretenu.
Ben Fortune
@Mritunjay merci, mais cela ne l'a pas résolu: /
user1576978
@BenFortune désolé, je garderai cela à l'esprit.
Mritunjay
@alandarev var app = express () ?? Je l'ai effectivement essayé, sans succès
user1576978

Réponses:

160

J'ai une solution pour rendre socket.io disponible dans 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 cette façon, vous pouvez accéder à la variable io dans votre app.js, et même la rendre disponible pour vos routes en définissant module.exports comme une fonction qui accepte io comme paramètre.

index.js

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

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

    return router;
}

Ensuite, passez io dans le module après sa configuration:

app.js

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

var routes = require('./routes/index')(io);
Gabriel Hautclocq
la source
1
Je suis nouveau sur NodeJS. Pouvez-vous s'il vous plaît expliquer ce qui se passe exactement sur cette ligne app.io = io;dans le app.jsfichier
Aryak Sengupta
3
Il s'agit simplement de placer la variable io dans l'objet app. Cela pourrait aussi être: app.io = socket_io ();
Gabriel Hautclocq
7
"... et même le rendre disponible pour vos itinéraires si vous le souhaitez." D'accord, mais comment? Ce serait formidable si vous pouviez donner un exemple sur la façon de procéder.
scaryguy
2
N'est-il pas mauvais d'attacher une propriété personnalisée à l' appobjet? Mieux vaut utiliser des symboles ou app.set().
Alexander Gonchiy
3
Pourquoi app.io = ioquand vous pourriez utiliser à la module.exports = { app, io }place
Manan Mehta
56

Une approche un peu différente pour initier socket.io, elle regroupe tout le code associé en un seul endroit:

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 cette façon, tout le socket.iocode associé dans un module et en fonction, je peux l'invoquer de n'importe où dans l'application.

Anatoly
la source
4
Cette réponse mérite plus de votes positifs! Très simple et propre, il garde les routes de socket en dehors de www , app.js et aussi en dehors de index.js (oui, en dehors de index.js ), ce fichier ne doit contenir que des routes HTTP Express.
adelriosantiago
1
Incroyable, très propre
sanket
3
Quelqu'un peut-il mettre à jour cela pour socket.io 2.0? Ça ne fonctionne pas pour moi. io.attach (serveur) et io.listen (serveur) lancent tous deux "impossible de lire la propriété X de non défini".
tsujp
1
Aussi parler à @tsujp mine fonctionne de la même manière. Vous devez frapper la bonne URL et ajouter le client socket.io et vous verrez que cela fonctionne
Tamb
J'ai un problème similaire à @tsujp, j'utilise socket.io 2.3.0 et je reçoisio.attach is not a function
raquelhortab
43

Il s'avère que c'était vraiment un problème de base sintax .... J'ai obtenu ces lignes de ce tutoriel de chat socket.io ...

sur ./bin/www, juste après var server = app.listen(.....)

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

alors maintenant je crée le fichier ../sockets/base.js et je mets ce petit bonhomme dedans:

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

Ouais! Maintenant ça marche ... Donc je suppose que je n'avais vraiment pas d'autre choix que de démarrer socket.io dans / bin / www, car c'est là que mon serveur http a été démarré. Le but est que maintenant je puisse créer des fonctionnalités de socket dans d'autres fichiers, en gardant la chose modulaire, enrequire('fileHere')(io);

<3

utilisateur1576978
la source
1
Le problème est que vous ne pouvez pas faire quelque chose commeio.on('connection', function(socket) { res.render('connection.jade') });
Gofilord
3
@Gofilord c'est parce qu'il va à l'encontre de tout le but des sockets ... ce dont vous avez besoin est un routage régulier qui inclut le rendu. Les sockets sont juste là pour envoyer des messages entre le client et le serveur sans requêtes http. peut-être lire cet article enterprisewebbook.com/ch8_websockets.html
Unispaw
19

Les anciens "expressjs", tout se passe dans le fichier "app.js". Ainsi, la liaison socket.io au serveur se produit également dans ce fichier. (BTW, on peut toujours le faire à l'ancienne, et supprimer bin / www)

Maintenant, avec les nouveaux expressjs, cela doit se produire dans le fichier "bin / www".

Heureusement, javascript / requirejs a facilité le passage d'objets. Comme l'a souligné Gabriel Hautclocq, socket.io est toujours "importé" dans "app.js" et il est attaché à l'objet "app" via une propriété

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

Le socket.io est rendu vivant en y attachant le serveur dans "bin / www"

app.io.attach(server); 

car l'objet "app" est passé dans "bin / www" plus tôt

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

C'est vraiment aussi simple que

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

Mais le faire de la manière «difficile» garantit que app.iocontient maintenant l'objet socke.io.

Maintenant, si vous avez besoin de cet objet socket.io également dans "routes / index.js" par exemple, utilisez simplement le même principe pour faire passer cet objet.

D'abord dans "app.js", faites

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

Puis dans "routes / index.js"

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

    var router = express.Router();



    return router;
 }

Donc "io" est injecté dans "index.js".

Zhe Hu
la source
9

Mise à jour de la réponse de Gabriel Hautclocq :

Dans le fichier www, le code doit apparaître comme suit en raison des mises à jour avec Socket.io. Attach est maintenant Listen.

/**
 * 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);`

De plus, pour que cette connexion fonctionne, il faut également implémenter l'API côté client. Ce n'est pas spécifique à Express, mais sans cela, l'appel de connexion ne fonctionnera pas. L'API est incluse dans

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

Incluez ce fichier sur le front-end et testez les éléments suivants:

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

Après avoir lu tous les commentaires, j'ai trouvé ce qui suit en utilisant Socket.io Server Version: 1.5.0

Problèmes que j'ai rencontrés:

  1. var sockIO = require ('socket.io') doit être var sockIO = require ('socket.io') () . (Crédit à: Zhe Hu )

  2. sockIO.attach doit être sockIO. écouter (Crédit à: rickrizzo )

Pas

  1. Installez Socket.io avec la commande suivante:

    npm install --save socket.io
  2. Ajoutez ce qui suit à app.js :

    var sockIO = require('socket.io')();
    app.sockIO = sockIO;
  3. Dans bin / www , après var server = http.createServer (app) , ajoutez ce qui suit:

    var sockIO = app.sockIO;
    sockIO.listen(server);
  4. Pour tester la fonctionnalité, dans app.js , vous pouvez ajouter la ligne:

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

Un tutoriel pour les débutants de Cedric Pabst
voici les brèves bases du lien pour un chat d'application:

en utilisant express-generate et le moteur ejs utilisable dans tous les fichiers .ejs routage standard dans express-generate

éditez le fichier bin \ www et ajoutez ce app.io.attach (serveur); comme ça

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

modifier dans 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;

modifier dans 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>

Amusez-vous :) et merci beaucoup à Cedric Pabst

AnnaBanana
la source
2

Certaines réponses précédentes ne fonctionnent pas et d'autres sont trop compliquées. Essayez plutôt la solution suivante ...

Installez les modules de nœud socket.io côté serveur et côté client:

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

Du côté serveur

Ajoutez le code suivant à bin / www après la définition du serveur, 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' });
});

Côté client

Si vous utilisez webpack, ajoutez le code suivant à votre fichier 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)
});

Terminé. Visitez votre site et consultez la console développeur js du navigateur.

s2t2
la source