Использование socket.io в Express 4 и экспресс-генератора / bin / www

93

Итак, дело в том, что я пытаюсь использовать socket.io в экспресс-проекте. После запуска Express Js 4 я обновил свой экспресс-генератор, и теперь начальные функции приложения ./bin/wwwперешли в файл, включая эти переменные (содержимое файла 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 в качестве отправной точки моего приложения?

user1576978
источник
Вам не нужно вводить импорт ./bin/www.. Просто положите его туда же, где и ваш var app.
alandarev 07
15
Я бы хотел, чтобы люди перестали предлагать экспресс-io. Он устарел и больше не обслуживается.
Бен Форчун
@Mritunjay, спасибо, но это не решило проблему: /
user1576978 07
@BenFortune, извините, я буду иметь это в виду.
Mritunjay 07
@alandarev var app = express () ?? Я пробовал на
самом деле

Ответы:

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файле
Aryak СЕНГУПТА
3
Это просто вопрос помещения переменной io в объект приложения. Это также может быть: app.io = socket_io ();
Габриэль Хаутклок,
7
«... и даже сделать его доступным для ваших маршрутов, если хотите». Хорошо, а как? Было бы здорово, если бы вы могли привести пример, как это сделать.
scaryguy
2
Разве не плохо прикрепить к appобъекту настраиваемое свойство ? Лучше использовать символы или app.set().
Александр Гончий
3
Почему, app.io = ioкогда вы могли бы использовать module.exports = { app, io }вместо этого
Манан Мета
59

Немного другой подход к инициации socket.io, он группирует весь связанный код в одном месте:

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

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

Анатолий
источник
4
Этот ответ заслуживает большего количества голосов! Очень простой и понятный, он сохраняет маршруты сокетов вне www , app.js, а также вне index.js (да, вне index.js ), этот файл должен содержать только маршруты Express HTTP.
adelriosantiago
1
Потрясающе, очень чисто
Sanket
3
Может ли кто-нибудь обновить это для socket.io 2.0? У меня это не работает. io.attach (сервер) и io.listen (сервер) оба бросают "не может прочитать свойство X неопределенного".
Jordan
1
Также, чтобы поговорить с @tsujp, у меня работает то же самое. Вам нужно нажать на правильный URL и добавить клиент socket.io, и вы увидите, что он работает
Тамб
У меня проблема, аналогичная @tsujp, я использую socket.io 2.3.0 и получаю io.attach is not a function
raquelhortab
43

Оказывается, это действительно была какая-то основная проблема с синтаксисом ... Я взял эти строки из этого урока по чату 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

user1576978
источник
1
Проблема в том, что вы не можете сделать что-то вродеio.on('connection', function(socket) { res.render('connection.jade') });
Gofilord
3
@Gofilord, потому что он побеждает всю цель сокетов ... вам нужна регулярная маршрутизация, которая включает рендеринг. Сокеты предназначены только для отправки сообщений между клиентом и сервером без HTTP-запросов. возможно, прочтите эту статью enterpriseewebbook.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); 

потому что объект "приложение" передается в "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 (app) добавьте следующее:

    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-generate и движок ejs, который можно использовать в каждом файле .ejs, стандартную маршрутизацию в express-generate

отредактируйте файл bin \ www и добавьте этот app.io.attach (server); как это

...
/*
 * 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 в браузере.

s2t2
источник