Використання socket.io в Express 4 та експрес-генератора / bin / www


93

Ось така угода: я намагаюся використовувати socket.io у експрес-проекті. Після запуску Express Js 4 я оновив свій експрес-генератор, і тепер початкові функції програми переходять у ./bin/wwwфайл, включаючи ці vars (вміст файлу www: http://jsfiddle.net/avMa5/ )

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

(перевірте це до того npm install -g express-generatorчасуexpress myApp

зважаючи на це, давайте згадаємо, як документи socket.io просять нас запустити його:

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

Гаразд, але я не можу зробити це всередині app.js, як рекомендується. Це слід зробити в ./bin/www, щоб працювати. в ./bin/www ось що я можу зробити, щоб це запрацювало:

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

Гаразд, це працює, але я не можу використовувати io var деінде ще, і я дійсно не хочу розміщувати свої функції socket.io у wwwфайлі.

Я припускаю , що це тільки базовий синтаксис, але я не можу отримати цю роботу, навіть не використовуючи module.exports = serverабо server.exports = serverні module.exports.io = app(io)на WWW файл

Тож питання полягає в тому: як я можу використовувати socket.io, маючи цей файл / bin / www як початкову точку мого додатка?


Вам не потрібно поміщати імпорт ./bin/www.. Просто поставте його туди ж, де і ваш var app.
alandarev

15
Я хотів би, щоб люди перестали пропонувати express-io. Він застарів і більше не підтримується.
Ben Fortune

@Mritunjay дякую, але це не вирішило: /
user1576978

@BenFortune вибачте, я буду це пам’ятати.
Мрітунджай

@alandarev var app = express () ?? Я фактично спробував, успіху не було
user1576978 07

Відповіді:


160

У мене є рішення, як зробити socket.io доступним у 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 );

(...)

Таким чином, ви можете отримати доступ до змінної io у своєму app.js і навіть зробити її доступною для своїх маршрутів, визначивши module.exports як функцію, яка приймає io як параметр.

index.js

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

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

    return router;
}

Потім передайте io в модуль після його налаштування:

app.js

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

var routes = require('./routes/index')(io);

1
Я новачок у NodeJS. Ви можете пояснити, що саме відбувається у цьому рядку app.io = io;у app.jsфайлі
Аряк Сенгупта

3
Це просто питання розміщення змінної io в об’єкт програми. Це також може бути: app.io = socket_io ();
Габріель Хаутклок

7
"... і навіть зробити його доступним для ваших маршрутів, якщо хочете." Гаразд, але як? Було б чудово, якби ви могли навести приклад, як це зробити.
scaryguy

2
Чи не погано приєднати до appоб’єкта спеціальну властивість ? Краще використовувати символи або app.set().
Олександр Гончій

3
Чому, app.io = ioколи ти міг використовувати module.exports = { app, io }замість цього
Манан Мехта

56

Трохи інший підхід до ініціації socket.io, він групує всі пов'язані коди в одному місці:

смітник / 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

Таким чином, весь socket.ioпов'язаний код в одному модулі та функції з нього я можу викликати з будь-якої точки програми.


4
Ця відповідь заслуговує на більше голосів! Дуже простий і чистий, він зберігає маршрути сокетів за межами www , app.js, а також за межами index.js (так, за межами index.js ), цей файл повинен містити лише експрес-маршрути HTTP.
adelriosantiago

1
Дивовижний, дуже чистий
санкет

3
Хтось може оновити це для socket.io 2.0? Це не працює для мене. io.attach (сервер) та io.listen (сервер) обидва видають "неможливо прочитати властивість X з невизначеним".
tsujp

1
Також розмова з @tsujp mine працює так само. Вам потрібно натиснути потрібну URL-адресу та додати клієнт socket.io, і ви побачите, як це працює
Tamb

У мене подібна проблема, як @tsujp, я використовую socket.io 2.3.0 і отримуюio.attach is not a function
raquelhortab

43

Виявляється, це справді була якась основна проблема sintax .... Я отримав ці рядки з цього підручника чату socket.io ...

./bin/www, відразу після var server = app.listen(.....)

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

так що тепер я створюю файл ../sockets/base.js і поміщаю цього маленького хлопця всередину:

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

Ага! Зараз це працює ... Отже, я думаю, у мене насправді не було іншого варіанту, окрім запуску socket.io всередині / bin / www, тому що саме там був запущений мій http-сервер. Мета полягає в тому, що тепер я можу створити функціональність сокета в інших файлах, зберігаючи річ модульноюrequire('fileHere')(io);

<3


1
Проблема в тому, що ти не можеш зробити щось на зразокio.on('connection', function(socket) { res.render('connection.jade') });
Gofilord

3
@Gofilord це тому, що він переборює цільове призначення сокетів ... Вам потрібна звичайна маршрутизація, яка включає візуалізацію. Сокети просто тут, щоб надсилати повідомлення між клієнтом та сервером без запитів http. можливо прочитайте цю статтю Enterprisewebbook.com/ch8_websockets.html
Unispaw

19

Старий "expressjs", все відбувається у файлі "app.js". Отже, прив’язка socket.io до сервера також відбувається в цьому файлі. (До речі, все одно можна зробити це по-старому, і видалити bin / www)

Тепер з новим expressjs це має відбутися у файлі "bin / www".

На щастя, javascript / requirejs спростив передачу об’єктів навколо. Як зазначив Габріель Хаутклок, socket.io все ще "імпортується" в "app.js", і він приєднується до об'єкта "app" через властивість

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

Socket.io працює в реальному часі, приєднавши до нього сервер у "bin / www"

app.io.attach(server); 

оскільки об'єкт "app" раніше передається в "bin / www"

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

Це насправді так само просто

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

Але робити це "важким" способом гарантує, що app.ioзараз утримується об'єкт socke.io.

Тепер, якщо вам потрібен цей об'єкт socket.io також, наприклад, у "routes / index.js", просто використовуйте той самий принцип, щоб передавати цей об'єкт навколо.

Спочатку в "app.js", зробіть

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

Потім у "routes / index.js"

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

    var router = express.Router();



    return router;
 }

Тож "io" вводиться в "index.js".


9

Оновлення відповіді Габріеля Хаутклока :

У файлі www код повинен виглядати наступним чином через оновлення з Socket.io. Вкласти зараз Слухай.

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

Крім того, щоб це підключення працювало, потрібно також впровадити API на стороні клієнта. Це не стосується Express, але без нього виклик підключення не працюватиме. API включений до

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

Включіть цей файл на фронт-енд і протестуйте наступне:

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

7

Прочитавши всі коментарі, я придумав наступне, використовуючи версію сервера Socket.io: 1.5.0

Проблеми, з якими я стикався:

  1. var sockIO = require ('socket.io') має бути var sockIO = require ('socket.io') () . (Кредит: Чже Ху )

  2. sockIO.attach повинен бути sockIO. слухати (Кредит: rickrizzo )

Кроки

  1. Встановіть Socket.io за допомогою такої команди:

    npm install --save socket.io
  2. Додайте до app.js наступне :

    var sockIO = require('socket.io')();
    app.sockIO = sockIO;
  3. У bin / www після var server = http.createServer (додаток) додайте таке:

    var sockIO = app.sockIO;
    sockIO.listen(server);
  4. Щоб перевірити функціональність, в app.js можна додати рядок:

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

5

Підручник для початківців від Cedric Pabst
ось короткі основи з посилання на чат програми:

використовуючи express-generirate та ejs-движок, який можна використовувати в кожному стандартному маршрутизації файлу .ejs у express-generate

відредагуйте файл bin \ www і додайте цей app.io.attach (сервер); подобається це

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

редагувати в 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;

редагувати в 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>

Веселіться :) і велике спасибі Седрику Пабсту


2

Деякі попередні відповіді не працюють, а інші надмірно складні. Спробуйте замість цього таке рішення ...

Встановіть модулі вузла socket.io на стороні сервера та клієнта:

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

На стороні сервера

Додайте наступний код до bin / www після визначення сервера 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' });
});

З боку клієнта

Якщо ви використовуєте webpack, додайте наступний код у файл 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)
});

Готово. Відвідайте свій сайт і перевірте консоль розробника js браузера.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.