ใช้ socket.io ใน Express 4 และ express-generator's / bin / www


93

นี่คือข้อตกลง: ฉันกำลังพยายามใช้ socket.io ในโครงการด่วน หลังจากที่ Express Js 4 ถูก lauched ฉันได้อัปเดตโปรแกรมสร้างด่วนของฉันและตอนนี้ฟังก์ชั่นเริ่มต้นของแอพจะเข้าสู่./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 ขอโทษฉันจะเก็บไว้ในใจ
Mritunjay

@alandarev var app = ด่วน () ?? ฉันพยายามอย่าง
จริงจัง

คำตอบ:


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 Sengupta

3
เป็นเพียงเรื่องของการใส่ตัวแปร io ลงในวัตถุของแอป อาจเป็น: app.io = socket_io ();
Gabriel Hautclocq

7
"... และแม้กระทั่งทำให้พร้อมใช้งานในเส้นทางของคุณหากคุณต้องการ" เอาล่ะ แต่ยังไง จะดีมากถ้าคุณสามารถยกตัวอย่างวิธีการทำ
Scaryguy

2
การแนบคุณสมบัติที่กำหนดเองเข้ากับวัตถุนั้นไม่เลวappหรือ ใช้สัญลักษณ์หรือapp.set().
Alexander Gonchiy

3
ทำไมapp.io = ioเมื่อคุณใช้module.exports = { app, io }แทนได้
Manan Mehta

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 แล้วคุณจะเห็นว่ามันใช้งานได้
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 นั่นเป็นเพราะมันเอาชนะจุดประสงค์ทั้งหมดของซ็อกเก็ต ... สิ่งที่คุณต้องการคือการกำหนดเส้นทางปกติซึ่งรวมถึงการเรนเดอร์ Sockets อยู่ที่นี่เพื่อส่งข้อความระหว่างไคลเอนต์และเซิร์ฟเวอร์โดยไม่ต้องร้องขอ http อาจจะอ่านบทความนี้enterprisewebbook.com/ch8_websockets.html
Unispaw

19

"expressjs" แบบเก่าทุกอย่างเกิดขึ้นในไฟล์ "app.js" ดังนั้นการเชื่อมต่อ socket.io กับเซิร์ฟเวอร์ก็เกิดขึ้นในไฟล์นั้นด้วย (BTW สามารถทำได้ด้วยวิธีเดิมและลบ bin / www)

ตอนนี้ด้วย Expressjs ใหม่จำเป็นต้องเกิดขึ้นในไฟล์ "bin / www"

โชคดีที่ javascript / requirejs ทำให้การส่งผ่านสิ่งของต่างๆเป็นเรื่องง่าย ดังที่ Gabriel Hautclocq ชี้ให้เห็นว่า 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 นี้ใน "route / index.js" เช่นกันให้ใช้หลักการเดียวกันเพื่อส่งผ่านวัตถุนั้นไปรอบ ๆ

อันดับแรกใน "app.js" ให้ทำ

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

จากนั้นใน "route / 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

อัปเดตการตอบสนองของGabriel Hautclocq :

ในไฟล์ www รหัสควรปรากฏดังต่อไปนี้เนื่องจากการอัพเดตด้วย Socket.io Attach is now 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);`

นอกจากนี้การเชื่อมต่อให้ทำงานได้นั้นต้องใช้ 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 = ต้อง ( 'socket.io')ควรจะ var sockIO = ต้อง ( 'socket.io') () (เครดิต: Zhe Hu )

  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 ต่อไป
นี้เป็นข้อมูลเบื้องต้นสั้น ๆ จากลิงก์สำหรับการแชทในแอป:

โดยใช้การสร้างแบบด่วนและเอ็นจิ้น ejs ที่ใช้งานได้ในทุกการกำหนดเส้นทางมาตรฐานของไฟล์. ejs ในการสร้างแบบด่วน

แก้ไขไฟล์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>

ขอให้สนุก :) และขอบคุณCedric Pabst มากมาย


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 ของเบราว์เซอร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.