【问题标题】:Multiply io.on("connection")乘 io.on("连接")
【发布时间】:2016-01-18 01:35:23
【问题描述】:

每次页面更新后,我都有 +1 套接字连接..

module.exports = function(io, client) {
var GameController = {
   gamePage: function(req, res) {
       client.hget('games', 'game.' + req.params.id, function (err, result) {
           if (err) return result(err);
           var game = JSON.parse(result);

           io.on('connection', function (socket) {
               console.log('send');
               console.log(socket.id);
               io.emit('get_bets', game.players);
           });

           res.render('pages/game', {
               title: 'Game - ' + req.params.id,
               user: req.user,
               game: game
           });
       });
   };
return GameController;
});

路由文件:

module.exports = function(io, client) {
   var express = require('express');
   var router = express.Router();
   var GameController = require('controllers/GameController')(io, client); 
   router.get('/:id', GameController.gamePage);
   ...
   return router;
};

客户端反应:

var Game = React.createClass({
   getInitialState: function() {
     this.socket = io();

     return {
         bets: null
     }
   },
 socketGetBets: function() {
   var that = this;
   this.socket.on('get_bets', function(data) {
       console.log('get bets');
       that.setState({ bets: data });
   });
   this.socket.on('rand', function(data) {
       console.log(data);
   });
 },
...

但调试后我发现什么问题不在客户端。

app.js 文件:

var socket_io = require('socket.io');

var io = socket_io();
app.io = io;
//route
var game = require('./routes/games')(io, client);

bin/www 文件:

var server = http.createServer(app);

var io     = app.io;
io.attach( server );

页面更新后,io.on("connection") 事件在控制台中显示“send”消息,第二次页面更新后,我有“send”“send”,第三次更新 - “send”“send”“send ”等比出现内存泄漏警告。控制台日志 socked.id 多次显示相同的值。

【问题讨论】:

    标签: node.js express reactjs socket.io


    【解决方案1】:

    每次调用on,无论是io.on 还是socket.on,都在注册一个事件处理程序。在这种情况下,您可能不想在路由内调用io.on('connection'),因为每次访问该路由时您都会注册一个新的连接处理程序。这就是您看到控制台中记录了累积消息的原因。

    事实上,您可能根本不想将快速路由与套接字函数混合使用,因为它们是不同的协议,并且会相互独立地工作。

    // server side
    
    // this should only be called once per connection.
    io.on('connection', function (socket) {
      // handle socket protocol stuff.. fetching server data, sending data
      socket.on('fetch bets', function() {
        // get game.players from server       
    
        // updating other sockets
        io.emit('get_bets', game.players);
      })
    })
    
    app.get('/route', function (req, res) {
      // handle http protocol stuff.. fetching server data, sending data
    
      // send data back to caller
      res.json(data)
    })
    

    这同样适用于您客户端的socket.on。看起来您每次调用 socketGetBets 时都会添加一个新的 'get_bets' 事件处理程序。

    相反,您可能希望一次注册该事件处理程序,可能在componentDidMountcomponentWillMount 中。此外,由于可以将套接字连接视为您的应用程序的全局连接,因此您可以在应用程序上方创建连接。

    // client side
    
    var socket = io()
    
    var Game = React.createClass({
      getInitialState: function() {
        return {
          bets: null
        }
      },
      componentWillMount: function() {
        var that = this
        socket.on('get_bets', function(data) {
          that.setState({ bets: data })
        })
      }
    ...
    

    【讨论】:

    • 感谢您的精彩回答!还有一个小问题:我需要在客户端 io.emit('fetch bets') 才能访问 io.emit('get_bets', game.players);在服务器端?
    • 如果我无权访问 req param: 'game.' + req.params.id,如何在 io.on('connection', function (socket) 之后获取 redis 数据?
    • 通常我会为我的套接字事件添加前缀,以帮助我思考来自哪里的内容。 socket.emit('client:fetch bets'),在服务器上是 socket.on('client:fetch bets'),反之亦然。 req.params.id 已经来自客户端,对吗?它在 url 中,所以只需将它与您的套接字发射一起发送。 socket.emit('client:fetch bets', { id: 'whatever' })
    • 我有一个使用socket + react的小游戏应用,如果你想看看我在做什么github.com/zen-games/lobby
    • 我可以在没有其他库或框架的情况下获得 req.params.id 吗?
    猜你喜欢
    • 2020-01-12
    • 2016-11-10
    • 2011-10-29
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 2017-06-27
    相关资源
    最近更新 更多