【问题标题】:Using socket.io in Express 4 and express-generator's /bin/www在 Express 4 和 express-generator 的 /bin/www 中使用 socket.io
【发布时间】:2014-08-27 21:36:02
【问题描述】:

这就是交易:我正在尝试在一个快速项目中使用 socket.io。在 Express Js 4 发布后,我更新了我的 express-generator,现在应用程序初始函数进入 ./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 文件上。

我想这只是基本语法,但我无法让它工作,即使在 www 文件上使用 module.exports = serverserver.exports = servermodule.exports.io = app(io) 也不行

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

【问题讨论】:

  • 您不必将导入放在./bin/www. 中。只需将其放在您的var app 所在的相同位置即可。
  • 我希望人们不要再推荐 express-io。它已经过时,不再维护。
  • @Mritunjay 谢谢你,但它没有解决它:/
  • @BenFortune 抱歉,我会记住这一点的。
  • @alandarev var app = express() ??我确实试过了,没有成功

标签: javascript node.js express socket.io


【解决方案1】:

以下是将 Socket.io 添加到新生成的 Express-Generator 应用程序的方法:

  1. 创建一个包含你的 socket.io 逻辑的文件,例如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. 修改您的bin/www 启动器。有两个步骤:需要您的 Socket.io api 并在创建 HTTP 服务器后立即将 HTTP 服务器附加到您的 socket.io 实例:

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. 然后您只需在 index.html 中添加 Socket.io 客户端即可。在 &lt;/body&gt; 结束标记之前添加以下内容:

index.html

    (...)
    <script src="/socket.io/socket.io.js"></script>
    <script>
        var socket = io();
    </script>
</body>
</html>
  1. 终于可以启动 Express 服务器了:
  • 基于 Unix:DEBUG=myapp:* npm start
  • Windows:set DEBUG=myapp:* &amp; npm start

注 1

如果出于任何原因您需要访问 app.js 中的套接字 api,那么您可以导入 app.js 中的套接字 api,然后重新导出:

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

然后在您的 bin/www 启动器中,不要在自己的行中导入您的套接字 api,而是在您的应用程序中导入它:

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

注意 2 此答案已更新为使用最新的 Express Generator(撰写本文时为 4.16)和最新的 Socket.io(撰写本文时为 3.0.5)。

【讨论】:

  • 简单的就是把io变量放到app对象里面。也可以是:app.io = socket_io();
  • "...如果您愿意,甚至可以将其提供给您的路线。"好的,但是怎么做?如果您能举个例子说明如何做到这一点,那就太好了。
  • @GabrielHautclocq 我如何从我的路线访问它?欣赏它!
  • 将自定义属性附加到app 对象不是不好吗?最好使用符号或app.set()
  • 为什么 app.io = io 可以使用 module.exports = { app, io } 代替
【解决方案2】:

启动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 相关代码和其中的函数我可以从应用程序的任何位置调用。

【讨论】:

  • 这个答案值得更多的支持!非常简单和干净,它将套接字路由保持在 wwwapp.js 以及 index.js 之外(是的,在 index 之外.js),这个文件应该只包含 Express HTTP 路由。
  • 很棒,很干净
  • 谁能为socket.io 2.0更新这个?它不适合我。 io.attach(server) 和 io.listen(server) 都抛出“无法读取未定义的属性 X”。
  • 另外与@tsujp 我的工作相同。你必须点击正确的 url 并添加 socket.io 客户端,你会看到它工作
  • 我遇到了与@tsujp 类似的问题,我使用的是socket.io 2.3.0,我收到了io.attach is not a function
【解决方案3】:

事实证明这确实是一些基本的 sintax 问题....我从 this socket.io chat tutorial 得到这些行...

在 ./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..... }

是的!现在它可以工作了......所以我想我除了在 /bin/www 内启动 socket.io 之外别无选择,因为那是我的 http 服务器启动的地方。 目标是现在我可以在其他文件中构建套接字功能,保持事物模块化,require('fileHere')(io);

【讨论】:

  • 问题是,你不能做类似io.on('connection', function(socket) { res.render('connection.jade') });的事情
  • @Gofilord 那是因为它违背了套接字的全部目的......您需要的是包括渲染在内的常规路由。套接字只是在这里在没有 http 请求的情况下在客户端和服务器之间发送消息。也许阅读这篇文章enterprisewebbook.com/ch8_websockets.html
【解决方案4】:

旧的“expressjs”,一切都发生在文件“app.js”中。所以 socket.io 绑定到服务器也发生在该文件中。 (顺便说一句,仍然可以使用旧方法,删除 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 对象。

现在,如果您在“routes/index.js”中也需要这个 socket.io 对象,只需使用相同的原理来传递该对象即可。

首先在“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”中。

【讨论】:

    【解决方案5】:

    更新Gabriel Hautclocq的回复:

    在 www 文件中,由于 Socket.io 的更新,代码应如下所示。 Attach 现在是 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');
    

    【讨论】:

      【解决方案6】:

      在阅读了所有的 cmets 之后,我使用 Socket.io Server Version: 1.5.0

      得出以下结论

      我遇到的问题:

      1. var sockIO = require('socket.io') 应该是 var sockIO = require('socket.io')()。 (归功于:Zhe Hu

      2. sockIO.attach 应该是 sockIO.listen(来源: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!');
        });
        

      【讨论】:

        【解决方案7】:

        初学者教程 from Cedric Pabst
        以下是应用聊天链接中的简短基础知识:

        使用快速生成 和ejs引擎 可用于 express-generate 中的每个 .ejs 文件标准路由

        编辑文件 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>
        

        玩得开心:) 非常感谢 Cedric Pabst

        【讨论】:

          【解决方案8】:

          以前的一些答案不起作用,而另一些则过于复杂。请尝试以下解决方案...

          安装服务器端和客户端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 开发者控制台。

          【讨论】:

            猜你喜欢
            • 2015-02-25
            • 2016-04-01
            • 2014-06-03
            • 2015-02-28
            • 1970-01-01
            • 1970-01-01
            • 2014-06-23
            • 1970-01-01
            • 2017-08-27
            相关资源
            最近更新 更多