使用 Express4中的 socket.io 和 Express- 生成器的/bin/www

因此,这里的交易: 我试图在一个快速项目中使用 socket.io。在 Express Js 4发布之后,我更新了我的 Express 生成器,现在应用程序的初始函数进入 ./bin/www文件,包括那些 vars (www 文件内容: http://jsfiddle.net/avMa5/)

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

(通过 npm install -g express-generatorexpress myApp检查

话虽如此,让我们回想一下 Socket.io 文档是如何要求我们启动它的:

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

好吧,但我不能像推荐的那样,在应用程序里做。这个应该在。为了工作。进去。/bin/www 这就是我能做的让它工作的方法:

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

好的,这个可以,但是我不能在其他任何地方使用 io 变量,而且我真的不想把 socket.io 函数放在 www文件中。

我想这只是基本的语法,但是我不能让它工作,甚至不使用 module.exports = serverserver.exports = servermodule.exports.io = app(io)的 www 文件

所以问题是: 我如何使用 socket.io 将这个/bin/www 文件作为我的应用程序的起点?

62858 次浏览

It turns out it really was some basic sintax problem.... I got these lines from this socket.io chat tutorial...

on ./bin/www, just after var server = app.listen(.....)

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

so now I create the ../sockets/base.js file and put this little fellow inside it:

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

Yeah! Now it works... So i guess i really had no option other than starting socket.io inside /bin/www , because that is where my http server was started. The goal is that now i can build socket functionality in other file(s), keeping the thing modular, by require('fileHere')(io);

<3

Here is how you can add Socket.io to a newly generated Express-Generator application:

  1. Create a file that will contain your socket.io logic, for example socketapi.js:

socketapi.js:

const io = require( "socket.io" )();
const socketapi = {
io: io
};


// Add your socket.io logic here!
io.on( "connection", function( socket ) {
console.log( "A user connected" );
});
// end of socket.io logic


module.exports = socketapi;
  1. Modify your bin/www launcher. There are two steps: requiring your Socket.io api and attaching the HTTP server to your socket.io instance right after creating the HTTP server:

bin/www:

/**
* Module dependencies.
*/


var app = require('../app');
var debug = require('debug')('socketexpress:server');
var http = require('http');
let socketapi = require("../socketapi"); // <== Add this line


/**
* Get port from environment and store in Express.
*/


var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);


/**
* Create HTTP server.
*/


var server = http.createServer(app);
socketapi.io.attach(server); // <== Also add this line


(...)
  1. Then you just need to add the Socket.io client in your index.html. Add the following just before the </body> closing tag:

index.html

    (...)
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
</body>
</html>
  1. Finally you can start your Express server:
  • Unix based: DEBUG=myapp:* npm start
  • Windows: set DEBUG=myapp:* & npm start

Note 1

If for any reason you need access to your socket api in your app.js, then you could instead import your socket api in app.js, and re-export it:

app.js

var express = require('express');
var socketapi = require("./socketapi"); // <== Add this line
(...)
// You can now access socket.io through the socketapi.io object
(...)
module.exports = { app, socketapi }; // <== Export your app and re-export your socket API here

Then in your bin/www launcher, instead of importing your socket api on its own line, just import it along your app:

bin/www

var {app, socketapi} = require('../app'); // <== Import your app and socket api like this
(...)
var server = http.createServer(app);
socketapi.io.attach(server); // <== You still have to attach your HTTP server to your socket.io instance

Note 2 This answer was updated to work with the latest Express Generator (4.16 at time of writing) and latest Socket.io (3.0.5 at time of writing).

The old "expressjs", everything is happening in the file "app.js". So the socket.io binding to server also happens in that file. (BTW, one can still do it the old way, and remove bin/www)

Now with the new expressjs, it needs to happen in the "bin/www" file.

Fortunately, javascript/requirejs made it easy to pass objects around. As Gabriel Hautclocq pointed out, socket.io is still "imported" in "app.js" and it gets attached to "app" object via a property

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

The socket.io is made live by attaching to it the server in "bin/www"

app.io.attach(server);

because "app" object is passed into "bin/www" earlier

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

It's really just as simple as

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

But doing it the "difficult" way ensures that app.io now holds the socke.io object.

Now if you need this socket.io object also in "routes/index.js" for example, just use the same principle to pass that object around.

First in "app.js", do

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

Then in "routes/index.js"

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


var router = express.Router();






return router;
}

So "io" gets injected into "index.js".

A tutorial for beginners from Cedric Pabst
here are the short basics form the link for an app chat:

using express-generate and the ejs engine usable in every .ejs file standard routing in express-generate

edit the file bin\www and add this app.io.attach(server); like this

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

edit in 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;

edit in 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>

Have fun :) and thanks many to Cedric Pabst

Update to Gabriel Hautclocq's response:

In www file, the code should appear as the following due to updates with 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);`

Additionally getting that connection to work requires implementing the client side API as well. This isn't Express specific but without it the connect call won't work. The API is included in

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

Include this file on the front end and test with the following:

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

Some previous answers are not working and others are overly complicated. Try the following solution instead...

Install server-side and client-side socket.io node modules:

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

Server-side

Add the following code to bin/www after the server definition, 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' });
});

Client-side

If using webpack, add the following code to your webpack entry.js file:

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

Done. Visit your site and check the browser's js developer console.

After reading through all of the comments, I came up with the following using Socket.io Server Version: 1.5.0

Issues that I ran into:

  1. var sockIO = require('socket.io') should be var sockIO = require('socket.io')(). (Credit to: Zhe Hu)

  2. sockIO.attach should be sockIO.listen (Credit to: rickrizzo)

Steps

  1. Install Socket.io with the following command:

    npm install --save socket.io
    
  2. Add the following to app.js:

    var sockIO = require('socket.io')();
    app.sockIO = sockIO;
    
  3. In bin/www, after var server = http.createServer(app), add the following:

    var sockIO = app.sockIO;
    sockIO.listen(server);
    
  4. To test functionality, in app.js, you can add the line:

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

A little different approach to initiate socket.io, it groups all related code in one place:

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

In this way all socket.io related code in one module and function from it I can invoke from anywhere in application.