【问题标题】:Node.js how to use socket.io in express routeNode.js 如何在快速路由中使用 socket.io
【发布时间】:2019-10-17 16:43:27
【问题描述】:

在我的一个 node.js 脚本中,我尝试在快速路由中使用 socket.io。我发现了许多类似的问题,并尝试按照建议实施解决方案,但没有任何结果。可能是因为我对快递路线缺乏了解。我点击了以下链接,

How use socket.io in express routes with node.js

Use socket.io in expressjs routes instead of in main server.js file

这是我的 app.js

const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);

const PORT = 3000;
server.listen(PORT);
console.log('Server is running');
var api = require('./routes/api');

//app.use('/api', api);
app.use('/api', (req, res) => {
res.sendFile(__dirname + '/api.html');
});

app.get('/', (req, res) => {
   res.send("this is home location");
});

./routes 文件夹中的路由文件 api.js

var express = require('express');
var router = express.Router();
var fs = require("fs");
var bodyParser = require('body-parser');

const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);

console.log("inside api route");

router.get('/', function(req, res, next) {
console.log("api route called");

const connections = [];
var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]

io.sockets.on('connection',(socket) => {
    connections.push(socket);
    console.log(' %s sockets is connected', connections.length); // this is not printing

    socket.on('disconnect', () => {
       connections.splice(connections.indexOf(socket), 1);
    });

    socket.emit('server message', jsonobj);

 }); 
    //res.send(jsonobj) 
});

module.exports = router;

Socket.emit 未在我在路由使用时呈现的 html 页面上显示数据。我的html代码是,

//api.html

<!DOCTYPE html>
<html lang="en">

<body>
   <div class="container">
      <h1 class="jumbotron">
         Node js Socket io with  socket route example
      </h1>
      <div class="results">results</div>      
   </div>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
   <script>
    jQuery(document).ready(function() {
       var socket = io.connect();
       var jsondata = "";

       socket.on('server message', function(data){
         console.log('got data from server',data)
         jsondata = JSON.stringify(data);
         //console.log('jsondata',jsondata)
         $('.results').html(jsondata);
       });
    });   
 </script>
</body>
</html>

请建议我应该在 html 页面中获取路由套接字数据的内容。 谢谢

【问题讨论】:

  • 尝试拨打http://localhost:3000/api/api/
  • 感谢@Vikash。是的,它奏效了。但怎么会?以及如何使它适用于“localhost:3000/api”。请提出建议。
  • 因为在 app.use 和 router.get 这两个地方你都给出了相同的路由字符串'/api'
  • 嗨@Vikash Singh,这没有按预期工作。它没有在 html 页面上显示套接字数据。

标签: node.js express socket.io routes


【解决方案1】:

乍一看,您似乎将 URL 前缀删除了两次。一次在 app.js 中,再次在 api.js 中。

试试 localhost:port/api/api

如果是这种情况,请更改

router.get('/api', function(req, res, next){

router.get('/', function(req, res, next){

这将允许您点击 localhost:port/api 并访问您的端点。

【讨论】:

  • 嗨@user3424216,我很遗憾地说,但它仍然无法正常工作。我通过解决方案得到的响应是因为 res.send(jsonobj),而不是套接字。我试图在 html 中获取套接字,但它没有显示。我使用了“app.use('/api', (req, res) => { res.sendFile (__dirname + '/api.html'); }); 我也会相应地编辑问题。
【解决方案2】:

好的,让我们试着理解为什么首先需要通过路由内部的套接字发送数据。 Websocket 用于异步发送数据,而无需客户端发出请求。如果客户端已经在发出 HTTP 请求,那么您可以在 HTTP 响应中发送数据。

现在已经说过了,显然有一些用例,您必须根据某些 OTHER 用户请求的操作将数据发送到某些 WebSocket 通道。如果是这种情况,有多种方法可以做到这一点。一种简洁的方法是使用事件驱动架构

尝试这样的事情...在下面找到我的 cmets -

const express = require('express');
const router = express.Router();
const fs = require("fs");
const bodyParser = require('body-parser');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);

// move the socket connection outside of the route controller
// you must register the event listeners before anything else
const connections = [];

io.sockets.on('connection', (socket) => {
    connections.push(socket);
    console.log(' %s sockets is connected', connections.length); // this is not printing

    socket.on('disconnect', () => {
        connections.splice(connections.indexOf(socket), 1);
    });
});


// Event emitter for sending and receving custom events
const EventEmitter = require('events').EventEmitter;
const myEmitter = new EventEmitter();

myEmitter.on('my-event', function (jsonobj) {
    // do something here like broadcasting data to everyone
    // or you can check the connection with some logic and 
    // only send to relevant user
    connections.forEach(function(socket) {
        socket.emit('server message', jsonobj);
    });
});

router.get('/some-route', function (req, res, next) {  
    const jsonobj = [{ name: "john", score: 345 }, { name: "paul", score: 678 }]

    // emit your custom event with custom data
    myEmitter.emit('my-event', jsonobj);

    // send the response to avoid connection timeout
    res.send({ok: true});
});

module.exports = router;

【讨论】:

    【解决方案3】:

    我自己才刚刚开始理解这一点,但我认为你所在的位置很接近。

    在你的 app.js 中添加到文件末尾:

    const express = require('express');
    const app = express();
    const server = require('http').createServer(app);
    const io = require('socket.io').listen(server);
    
    const PORT = 3000;
    server.listen(PORT);
    console.log('Server is running');
    var api = require('./routes/api');
    
    //app.use('/api', api);
    app.use('/api', (req, res) => {
    res.sendFile(__dirname + '/api.html');
    });
    
    app.get('/', (req, res) => {
       res.send("this is home location");
    });
    
    app.set("socketio", io);    // <== this line
    

    将“io”变量存储在“socketio”中。您可以在任何其他“.js”文件中获取它。

    var express = require('express');
    var router = express.Router();
    var fs = require("fs");
    var bodyParser = require('body-parser');
    
    const app = express();
    const server = require('http').createServer(app);
    //const io = require('socket.io').listen(server); // <== change this
    const io = app.get("socketio"); // <== to this
    
    console.log("inside api route");
    
    router.get('/', function(req, res, next) {
    console.log("api route called");
    
    const connections = [];
    var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]
    
    io.sockets.on('connection',(socket) => {
        connections.push(socket);
        console.log(' %s sockets is connected', connections.length); // this is not printing
    
        socket.on('disconnect', () => {
           connections.splice(connections.indexOf(socket), 1);
        });
    
        socket.emit('server message', jsonobj);
    
     }); 
        //res.send(jsonobj) 
    });
    
    module.exports = router;
    

    您应该使用其他“.js”文件中所需的任何其他变量来执行此操作。

    另请注意,在您的文件中,您正在重新设置变量。最好像我用“io”向你展示的那样做。我设置的其他文件中唯一的变量是“app”本身。

    希望这会有所帮助...

    【讨论】:

    • 嗨@WLGfx。 app.set("socketio", io);这条线看起来很吸引人。我尝试了这个解决方案,但没有奏效。我注意到它没有进入路由器部分。 “调用的 api 路由”未在“localhost:3000/api”上进入控制台
    【解决方案4】:

    您尝试在单个项目中从两个不同的位置创建和启动服务器,这很不方便。你只需要一些清理,仅此而已。

    app.js

    const express = require('express');
    const app = express();
    const server = require('http').createServer(app);
    const io = require('socket.io').listen(server);
    
    
    // Listen to sockets here instead of listening in routes/api.js
    const connections = [];
    var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]
    
    io.sockets.on('connection',(socket) => {
      connections.push(socket);
      console.log(' %s sockets is connected', connections.length); // this is not printing
    
      socket.on('disconnect', () => {
         connections.splice(connections.indexOf(socket), 1);
      });
    
      socket.emit('server message', jsonobj);
    
    });
    
    const PORT = 3000;
    server.listen(PORT);
    console.log('Server is running');
    var api = require('./routes/api');
    
    //app.use('/api', api);
    app.use('/api', (req, res) => {
    res.sendFile(__dirname + '/api.html');
    });
    
    app.get('/', (req, res) => {
       res.send("this is home location");
    });
    

    routes/api.js

    var express = require('express');
    var router = express.Router();
    var fs = require("fs");
    var bodyParser = require('body-parser');
    
    // Comment these out
    // const app = express();
    // const server = require('http').createServer(app);
    // const io = require('socket.io').listen(server);
    
    console.log("inside api route");
    
    router.get('/', function(req, res, next) {
    console.log("api route called");
    
      // Comment these out
    
      // const connections = [];
      // var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]
    
      // io.sockets.on('connection',(socket) => {
      //     connections.push(socket);
      //     console.log(' %s sockets is connected', connections.length); // this is not printing
    
      //     socket.on('disconnect', () => {
      //        connections.splice(connections.indexOf(socket), 1);
      //     });
    
      //     socket.emit('server message', jsonobj);
    
      //  }); 
          //res.send(jsonobj) 
    });
    
    module.exports = router;
    

    保留您的 api.html 原样。希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2018-10-06
      • 1970-01-01
      • 2013-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-28
      • 2015-10-27
      相关资源
      最近更新 更多