【问题标题】:socket.emit not firing inside post requestsocket.emit 没有在 post 请求中触发
【发布时间】:2016-08-11 12:40:53
【问题描述】:

我将io.on('connection', function (socket) { 包裹在一个帖子请求中。然后我在帖子请求中调用socket.emit('news', 'username taken');。出于某种原因,当我进行此调用时,它不会向客户端发送任何内容。当我将发射更改为io.emit('connection', function (socket)) 它工作并将数据发送到客户端。我对该解决方案的问题是使用 io.emit 会将数据发送到所有连接的套接字。我的问题是如何在这个帖子请求中使用 socket.emit。

io.on('connection', onConnection);

function onConnection(sock) {
 sock.emit('news', 'username is taken');
}

app.post('/signup', function(req, res) {

    var userDetails = User({
        firstname: req.body.firstname,
        username: req.body.username,
        email: req.body.email,
        password: bcrypt.hashSync(req.body.password1, bcrypt.genSaltSync(10))
    });

    User.findOne({
        $or: [ { 'username': req.body.username}, {'email': req.body.email}]
    }, function(err, user) {
        if (user) {
              if(user.username === req.body.username){
              onConnection();
              console.log('username is taken');
            } else {
            }
            if(user.email === req.body.email){
              console.log('email is taken')
            } else {
            }
        } else {
          userDetails.save(function(err) {
            if (err) throw err;
          });
          res.redirect('/');
          console.log('change to login')
        }
        if (err) {
            return done(err);
        }
    });

   });

});

【问题讨论】:

  • 埃克。不要将app.post() 放入io.on() EVER。这是错误的。您的app.post() 处理程序将可用于与该路由匹配的所有传入请求,并且您将为每个连接的单个用户添加一个新的重复处理程序,并且将为每个单个用户调用所有app.post() 处理程序。没办法,这是永远正确的。
  • 感谢您的澄清,我也想知道这一点。
  • 我看到你改变了一些东西,但你也不能把 io.on('connection', ...) 放在你的 app.post() 里面。这将为该事件创建重复的处理程序。回到开头,用文字准确描述您要解决的问题。
  • 不,这也不起作用。请参阅我之前的评论。
  • 请停止猜测代码。你不能在没有参数的情况下调用onConnection() 并期望它在你的最新版本中工作。请用文字准确描述您想要做什么,然后我们可以帮助您。如果目标是向发出 app.post() 请求的用户发送 socket.io 消息,那么请用文字描述一下,我们可以提供一些想法。

标签: node.js socket.io


【解决方案1】:

解决此问题的常用方法是使用会话中间件,该中间件会在加载网站的第一页时建立用户会话。然后,当用户连接到 socket.io 时,您会将 socket.id 放入该用户的会话中。然后,当您获得app.post() 并且想要发送到他们的socket.io 连接时,您将在会话中查找该用户,获取该用户的socket.id,然后使用它查找套接字。获得套接字后,您可以向他们发送消息。

您使用会话连接 socket.io 连接和app.post()。没有在另一个事件处理程序中设置事件处理程序。

【讨论】:

  • 我想我需要为每个连接的唯一用户创建套接字 ID。
  • @JohnAnderson - socket.io 已经有socket.id 供您在连接时使用。而且,当您需要发送给该用户时,您可以使用该 id 在 socket.io 数据结构中查找套接字。
【解决方案2】:

我刚刚解决了我的问题。我所做的是创建一个名为 socket1 的变量。然后我在 io.on 匿名函数中将 socket 参数分配给 socket1。然后,我将套接字作为通用变量,我可以在代码中的任何位置调用它。我不确定这在编程上是否正确,但它有效。

var SOCKET_LIST = {};

var socket1;

io.on('connection', function (socket) {
    SOCKET_LIST[socket.id] = socket;
    socket1 = socket;
    socket.emit('news', 'username taken');
});

app.post('/signup', function(req, res) {

var userDetails = User({
    firstname: req.body.firstname,
    username: req.body.username,
    email: req.body.email,
    password: bcrypt.hashSync(req.body.password1, bcrypt.genSaltSync(10))
});

User.findOne({
    $or: [ { 'username': req.body.username}, {'email': req.body.email}]
}, function(err, user) {
    if (user) {
        if(user.username === req.body.username){
          socket1.emit('news', 'username taken');
          console.log('username is taken');
        } else {
        }
        if(user.email === req.body.email){
          io.emit('news', 'email taken');
          console.log('email is taken')
        } else {
        }
    } else {
      userDetails.save(function(err) {
        if (err) throw err;
      });
      res.redirect('/');
      console.log('change to login')
    }
    if (err) {
        return done(err);
    }
});

});

【讨论】:

  • 此解决方案仅适用于只有一个用户的网站。一旦您的第二个用户连接,它将无法正常工作。有关解决方案的一般方法,请参阅我的答案。
  • 我更新了关于@jfriend00 答案的答案。
  • @jfriend00 你认为这样的事情可行吗?
  • 你不需要做SOCKET_LIST[socket.id] = socket;io.sockets.connected 已经是 socket.id 的索引 - 由 socket.io 自动维护。另外,您的方案会泄漏套接字对象,因为您从不从数据结构中删除套接字。
  • 如果我已经将 socket.id 编入索引,我该如何搜索已连接的特定用户?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-01
  • 1970-01-01
  • 2022-11-19
  • 1970-01-01
  • 2021-11-16
  • 2017-11-28
相关资源
最近更新 更多