代码之家  ›  专栏  ›  技术社区  ›  Chico3001

socket.io刷新浏览器时添加连接

  •  0
  • Chico3001  · 技术社区  · 6 年前

    我在nodejs应用程序上添加socket.io(我是新手btw),当我刷新网页时,按chrome上的f5键,会根据服务器日志创建一个新的socket:

    用户连接swpg6fv9mjmmolzraaaa
    用户断开swpg6fv9mjmmolzraaaa
    用户连接的gvtxcnjr6sc4dw7caaab
    用户连接的gvtxcnjr6sc4dw7caaab
    用户断开了gvtxcnjr6sc4dw7caaab
    用户断开了gvtxcnjr6sc4dw7caaab
    用户连接的PwPjzbvv_uu-lnvl4raaac
    用户连接的PwPjzbvv_uu-lnvl4raaac
    用户连接的PwPjzbvv_uu-lnvl4raaac
    用户断开了PWPJZBV UUUVL4RAAAC
    用户断开了PWPJZBV UUUVL4RAAAC
    用户断开了PWPJZBV UUUVL4RAAAC
    用户连接的sp7ljarrh6hrevp7aaad
    用户连接的sp7ljarrh6hrevp7aaad
    用户连接的sp7ljarrh6hrevp7aaad
    用户连接的sp7ljarrh6hrevp7aaad
    用户已断开SP7LJARRHREVP7AAD
    用户已断开SP7LJARRHREVP7AAD
    用户已断开SP7LJARRHREVP7AAD
    用户已断开SP7LJARRHREVP7AAD
    用户已连接-86W ITTDWrsyevgaae
    用户已连接-86W ITTDWrsyevgaae
    用户已连接-86W ITTDWrsyevgaae
    用户已连接-86W ITTDWrsyevgaae
    用户已连接-86W ITTDWrsyevgaae

    你知道为什么会这样吗?

    这是我的代码:

    小精灵:

    "use strict";
    
    const express = require('express');
    const app = express();
    const http = require('http').Server(app);
    const socket = require('socket.io')(http);
    
    const opn = require('opn');
    
    const login = require('./scripts/login.js');
    const main = require('./scripts/main.js')(socket);
    const init = require('./scripts/init.js');
    const config = require('./scripts/config.js');
    
    app.use(express.static('public'));
    app.set('view engine', 'ejs');
    http.listen(3000, function () {
        console.log('==> Servidor iniciado -- Puerto 3000');
    });
    
    opn('http://localhost:3000');
    
    app.use('/', main);
    

    MIN JS

    "use strict";
    
    const express = require('express');
    const router = express.Router();
    const main = function (socket) {
    
        // Home page route.
        router.get('/', function (req, res) {
            socket.on('connection', function (socket) {
                console.log('user connected ' + socket.id);
                socket.on('disconnect', function () {
                    console.log('user disconnected ' + socket.id);
                });
            });
    
            res.render('main', {
                page_name: 'main'
            });
        });
    
        return router;
    };
    
    module.exports = main;
    

    索引文件

    <script src="/socket.io/socket.io.js" charset="utf-8"></script>
    <script>
        var socket = io();
    
        socket.on('connect', function (data) {
            console.log('connected');
        });
    </script>
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   jfriend00    6 年前

    实际上,您没有获得多个连接,而是为 connection 事件,因此您最终会多次处理同一事件(导致出现多个连接)。

    当你放插座的时候。 connect 这样的路由处理程序中的事件侦听器:

    // Home page route.
    router.get('/', function (req, res) {
        socket.on('connection', function (socket) {
            console.log('user connected ' + socket.id);
            socket.on('disconnect', function () {
                console.log('user disconnected ' + socket.id);
            });
        });
    
        res.render('main', {
            page_name: 'main'
        });
    });
    

    那么,每次 / 路由被命中,您为 连接 事件。因此,当一个新的socket.io连接发生时,您有多个监听器来处理它,因此您要多次处理相同的连接(创建混乱的日志记录)。

    解决方案通常是将socket.io监听器移到任何路由处理程序之外,以便只安装一次。但是,如果由于其他原因将它们放在路由处理程序中,那么您还必须解决另一个问题。在任何情况下,socket.io侦听器都必须在任何路由处理程序之外,因此在服务器启动时只安装一次。

    也许是这样:

    "use strict";
    const router = require('express').Router();
    
    module.exports = function(io) {
    
        io.on('connection', function (socket) {
            console.log('user connected ' + socket.id);
            socket.on('disconnect', function () {
                console.log('user disconnected ' + socket.id);
            });
        });
    
        // Home page route.
        router.get('/', function (req, res) {
            res.render('main', {
                page_name: 'main'
            });
        });
    
        return router;
    };
    

    注意,在同一个作用域中也有两个变量,都命名为 socket . 这是一个糟糕的实践,因为它阻止了对更高范围的访问,并且在处理代码时通常会造成错误或混乱的机会。

    你的上级应该被命名为 io 以免与 插座 参数 连接 事件和 输入输出 是引用主socket.io服务器实例时的常规约定。