Korzystanie z socket.io w Express 4 i express-generator's / bin / www

93

Oto sprawa: próbuję użyć socket.io w projekcie ekspresowym. Po uruchomieniu Express Js 4 zaktualizowałem mój generator ekspresów i teraz początkowe funkcje aplikacji trafiają do ./bin/wwwpliku, w tym te vars (zawartość pliku www: http://jsfiddle.net/avMa5/ )

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

(sprawdź to do npm install -g express-generatorczasuexpress myApp

Biorąc to pod uwagę, pamiętajmy, jak dokumenty socket.io proszą nas o odpalenie go:

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

Ok, ale nie mogę tego zrobić w app.js, jak zalecane. Aby to zadziałało, należy to zrobić w ./bin/www. in ./bin/www oto, co mogę zrobić, aby działał:

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

Ok, to działa, ale nie mogę używać zmiennej io nigdzie indziej i naprawdę nie chcę umieszczać moich funkcji socket.io w wwwpliku.

Wydaje mi się, że to tylko podstawowa składnia, ale nie mogę tego uruchomić, nawet nie używając module.exports = serverani server.exports = serverani module.exports.io = app(io)w pliku www

Więc pytanie brzmi: jak mogę używać socket.io mając ten plik / bin / www jako punkt wyjścia mojej aplikacji?

user1576978
źródło
Nie musisz wprowadzać importu ./bin/www.. Po prostu umieść go w tym samym miejscu, w którym jesteś var app.
alandarev
15
Chciałbym, żeby ludzie przestali sugerować express-io. Jest przestarzały i nie jest już obsługiwany.
Ben Fortune,
@Mritunjay dziękuję, ale to nie rozwiązało problemu: /
user1576978
@BenFortune przepraszam, będę o tym pamiętać.
Mritunjay
@alandarev var app = express () ?? Właściwie spróbowałem, bez sukcesu
user1576978

Odpowiedzi:

160

Mam rozwiązanie umożliwiające udostępnienie socket.io w 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 );

(...)

W ten sposób możesz uzyskać dostęp do zmiennej io w pliku app.js, a nawet udostępnić ją dla swoich tras, definiując module.exports jako funkcję, która przyjmuje parametr io jako parametr.

index.js

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

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

    return router;
}

Następnie przekaż io do modułu po jego skonfigurowaniu:

app.js

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

var routes = require('./routes/index')(io);
Gabriel Hautclocq
źródło
1
Jestem nowy w NodeJS. Czy możesz wyjaśnić, co dokładnie dzieje się w tej linii app.io = io;w app.jspliku
Aryak Sengupta,
3
Jest to po prostu kwestia umieszczenia zmiennej io do obiektu aplikacji. Może to być również: app.io = socket_io ();
Gabriel Hautclocq
7
„... a jeśli chcesz, możesz nawet udostępnić go na swoich trasach”. Dobrze, ale jak? Byłoby wspaniale, gdybyś mógł podać przykład, jak to zrobić.
scaryguy
2
Czy nie jest źle dołączyć do appobiektu własność niestandardową ? Lepiej używaj symboli lub app.set().
Alexander Gonchiy,
3
Dlaczego, app.io = ioskoro możesz module.exports = { app, io }zamiast tego użyć
Manan Mehta
59

Trochę inne podejście do inicjowania socket.io, grupuje wszystkie powiązane kody w jednym miejscu:

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

W ten sposób cały socket.iopowiązany kod w jednym module i funkcje z niego mogę wywołać z dowolnego miejsca w aplikacji.

Anatolij
źródło
4
Ta odpowiedź zasługuje na więcej głosów! Bardzo prosty i przejrzysty , utrzymuje trasy gniazd poza www , app.js, a także poza index.js (tak, poza index.js ), ten plik powinien zawierać tylko trasy Express HTTP.
adelriosantiago
1
Niesamowite, bardzo czyste
sanket
3
Czy ktoś może zaktualizować to dla socket.io 2.0? Na mnie to nie działa. io.attach (serwer) i io.listen (serwer) zgłaszają „nie można odczytać właściwości X wartości undefined”.
Jordan
1
Również rozmowa z @tsujp działa tak samo. Musisz trafić we właściwy adres URL i dodać klienta socket.io, a zobaczysz, że działa
Tamb
Mam podobny problem jak @tsujp, używam socket.io 2.3.0 i dostajęio.attach is not a function
raquelhortab
43

Okazuje się, że to naprawdę był jakiś podstawowy problem z sintaxem ... Mam te linie z tego samouczka czatu socket.io ...

na ./bin/www, zaraz po var server = app.listen(.....)

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

więc teraz tworzę plik ../sockets/base.js i umieszczam w nim tego małego gościa:

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

Tak! Teraz to działa ... Więc myślę, że naprawdę nie miałem innej opcji niż uruchomienie socket.io w / bin / www, ponieważ tam został uruchomiony mój serwer http. Celem jest to, że teraz mogę zbudować funkcjonalność gniazda w innym pliku (plikach), zachowując modułowośćrequire('fileHere')(io);

<3

user1576978
źródło
1
Problem w tym, że nie da się zrobić czegoś takiegoio.on('connection', function(socket) { res.render('connection.jade') });
Gofilord
3
@Gofilord to dlatego, że pokonuje cały cel gniazd ... potrzebujesz zwykłego routingu, który obejmuje renderowanie. Gniazda służą tylko do wysyłania wiadomości między klientem a serwerem bez żądań http. może przeczytaj ten artykuł enterprisewebbook.com/ch8_websockets.html
Unispaw
19

Stare "expressjs", wszystko dzieje się w pliku "app.js". Zatem powiązanie socket.io z serwerem ma miejsce również w tym pliku. (BTW, nadal można to zrobić starym sposobem i usunąć bin / www)

Teraz, z nowymi expressjami, musi się to stać w pliku „bin / www”.

Na szczęście javascript / requirejs ułatwił przekazywanie obiektów. Jak zauważył Gabriel Hautclocq, socket.io jest nadal „importowany” do „app.js” i jest dołączany do obiektu „app” za pośrednictwem właściwości

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

Socket.io jest tworzone na żywo przez dołączenie do niego serwera w „bin / www”

app.io.attach(server); 

ponieważ obiekt „app” jest wcześniej przekazywany do „bin / www”

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

To naprawdę tak proste, jak

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

Ale zrobienie tego w „trudny” sposób gwarantuje, że app.ioteraz będzie trzymany obiekt socke.io.

Teraz, jeśli potrzebujesz tego obiektu socket.io również na przykład w "route / index.js", po prostu użyj tej samej zasady, aby przekazać ten obiekt.

Najpierw w „app.js” zrób

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

Następnie w „route / index.js”

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

    var router = express.Router();



    return router;
 }

Więc „io” zostaje wstawione do „index.js”.

Zhe Hu
źródło
9

Aktualizacja odpowiedzi Gabriela Hautclocqa :

W pliku www kod powinien wyglądać następująco ze względu na aktualizacje z Socket.io. Dołącz jest teraz Słuchaj.

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

Ponadto uzyskanie tego połączenia do pracy wymaga również zaimplementowania interfejsu API po stronie klienta. To nie jest specyficzne dla Express, ale bez niego połączenie connect nie będzie działać. API jest zawarte w

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

Dołącz ten plik do interfejsu użytkownika i przetestuj z następującymi elementami:

var socket = io.connect('http://localhost:3000');
rickrizzo
źródło
7

Po przeczytaniu wszystkich komentarzy, przy użyciu Socket.io Server Version: 1.5.0 wymyśliłem następujące rzeczy

Problemy, które napotkałem:

  1. var sockIO = require ('socket.io') powinno być var sockIO = require ('socket.io') () . (Kredyt dla: Zhe Hu )

  2. sockIO.attach powinno być sockIO. słuchaj (Credit to: rickrizzo )

Kroki

  1. Zainstaluj Socket.io za pomocą następującego polecenia:

    npm install --save socket.io
    
  2. Dodaj do app.js :

    var sockIO = require('socket.io')();
    app.sockIO = sockIO;
    
  3. W bin / www , po var server = http.createServer (app) , dodaj:

    var sockIO = app.sockIO;
    sockIO.listen(server);
    
  4. Aby przetestować funkcjonalność, w app.js możesz dodać wiersz:

    sockIO.on('connection', function(socket){
        console.log('A client connection occurred!');
    });
    
Brian
źródło
5

Samouczek dla początkujących autorstwa Cedric Pabst
zawiera krótkie podstawy z linku do czatu w aplikacji:

używając ekspresowego generowania i silnika ejs używanego w każdym standardowym routingu plików .ejs w ekspresowym generowaniu

edytuj plik bin \ www i dodaj ten plik app.io.attach (serwer); lubię to

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

edytować w 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;

edytuj w 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>

Baw się dobrze :) i dziękuję Cedricowi Pabstowi

AnnaBanana
źródło
2

Niektóre poprzednie odpowiedzi nie działają, a inne są zbyt skomplikowane. Zamiast tego wypróbuj następujące rozwiązanie ...

Zainstaluj moduły węzłów socket.io po stronie serwera i klienta:

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

Po stronie serwera

Dodaj następujący kod do bin / www po definicji serwera 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' });
});

Strona klienta

Jeśli używasz pakietu internetowego, dodaj następujący kod do pliku entry.js pakietu internetowego :

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)
});

Gotowe. Odwiedź swoją witrynę i sprawdź konsolę programisty js przeglądarki.

s2t2
źródło