socket.io 发出多次

socket.io emits multiple times

我有一个非常基本的例子。之前在堆栈溢出本身中多次询问过这个问题,但我无法得到正确的答案,所以我将使用这个基本示例。

服务器:

var app    = require('express')();
var server = require('http').Server(app);
var io     = require('socket.io')(server);

server.listen(3000);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
  socket.on('chat', function (data) {
    var op = false;
    if( data.id == '1234' ){
       op = 'yes';
    }else{
       op = 'no';
    } 
    socket.emit('result', { hello: op });
  });
});

客户:

<html>
    <body>
        <button onclick="check()">Test Me :-)</button>
        <script src="/socket.io/socket.io.js"></script>
        <script>
          var socket = io.connect('http://localhost:3000');

          var check = function(){

            var data = { id : '234'};
            socket.emit('chat', data);

            socket.on('result', function(data){
                console.log('The data is '+data)
            })
          }
        </script>
    </body>
</html>

当我第一次点击测试我按钮时 socket.emit('result', { 你好: 'world' }); 它被发射一次。在控制台中,我打印了这个:

console.log('The data is '+data)

但是当我再次点击时,我打印了三次:

console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data)

当我第三次点击时,我打印了六次:

console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data)
console.log('The data is '+data) 

就这样繁衍下去。

任何人都可以告诉我如何解决这个问题。 非常感谢您的帮助。谢谢!

我认为您正在向 'result' 添加越来越多的听众来检查您进行的每次调用。

第一次点击 -> 从调用 1 侦听器调用 1 console.log

第二次点击 -> 调用 1 console.log 来自调用 1 监听器 + 调用 2 console.log 来自调用 1 监听器 + 调用 2 console.log 来自调用 2 监听器

第三次 -> 之前的日志 + 来自调用 1 监听器的调用 3 console.log + 来自调用 2 监听器的调用 3 console.log 和来自调用 3 监听器的调用 3 console.log。

尝试将 'result' 的侦听器置于函数之外:

<html>
 <body>
    <button onclick="check()">Test Me :-)</button>
    <script src="/socket.io/socket.io.js"></script>
    <script>
      var socket = io.connect('http://localhost:3000');

       socket.on('result', function(data){
            console.log('The data is '+data)
        })
      var check = function(){

        var data = { id : '234'};
        socket.emit('chat', data);
      }
    </script>
 </body>
</html>

我没有读过这个问题,但我把它放在这里是为了帮助其他人,因为我还没有找到这种答案。

在我的例子中,我多次调用函数 next,就像这样

io.use(async (socket, next) => {
    let req = socket.request
    let res = req.res || {}

    someMiddleware()(req, res, next)
    anotherMiddleware({extended: false})(req, res, next)
    anotherMiddleware()(req, res, next)
    anotherMiddleware(req, res, next)
    anotherMiddleware()(req, res, next)
    anotherMiddleware()(req, res, next)
})

每次我调用中间件时,next 函数都会被调用,on('connection') 也会被调用。我要做的是覆盖 next 并将其放入最后一个中间件中,因此连接只被调用一次。

. . .
let originalNext = next
next = () => {} // NOW its not going to annoy anymore
someMiddleware()(req, res, next)
anotherMiddleware({extended: false})(req, res, next)
anotherMiddleware()(req, res, next)
anotherMiddleware(req, res, next)
anotherMiddleware()(req, res, next)
anotherMiddleware()(req, res, originalNext) //next get called <
. . . 

对于客户端,您可以使用 socket.once() 而不是 socket.on()。示例:

socket.once('result', function(data){
 console.log('The data is '+data)
})

参考:https://socket.io/docs/v3/listening-to-events/#socket-once-eventName-listener