使用 $.get 调用文件时,socket.io 事件不起作用

Posted

技术标签:

【中文标题】使用 $.get 调用文件时,socket.io 事件不起作用【英文标题】:socket.io event not working when calling a file with $.get 【发布时间】:2016-11-04 07:21:41 【问题描述】:

我一直在学习使用 socket 的 express,但我似乎无法让我的代码按照我想要的方式工作。基本上我正在做一个 $.get 调用,它通过并替换我的索引页面上的 html。这是在服务器确认添加的新用户满足正确要求后完成的。

$.get 完美运行,它通过其他文件 html 提取。然而,套接字事件随后停止工作,我不明白为什么。它应该做的是在聊天框旁边添加个人用户名,当有人输入内容时,它也应该反映这一点。

似乎服务器不喜欢我调用不同的文件或类似的东西?

这是我的 GIT 的直接链接:https://github.com/factordog/letsGuess 因此,如果您需要查看所有设置的方式可以直接检查,我不确定需要什么。

这是有问题的代码:

        $.get("./pages/game.html" ,function(data)
            console.log(data);
            $("#test").html(data);
        );

这是真正的客户端 js:

$(function($) 

    // Variables
    var socket          = io.connect(),// Creates the connection variable
        setUsername     = $("#setUsername"), //Form for when a user join
        newUser         = $("#username"), // Input for where user inputs a name
        userSuccess     = $(".successMessage"), // Success container for valid username
        userError       = $(".errorMessage"), // Error container for invalid username
        playerOne       = null, 
        playerTwo       = null;

    // Submit function for when a user submits their desired username
    setUsername.submit(function(e)
        // Prevent sumbit button default
        e.preventDefault();

        // Gets value of the username. function(data) allows us to reference the app.js
        // data which is the array of new users.
        socket.emit("new user", newUser.val(), function(data)
            // Checks if name is valid else displays an error
            if(data) 
                socket.on("full_lobby_check", function(data)
                    console.log(data.lobbyStatus);
                );
                // Fades out the login page
                userSuccess.removeClass("hide");
                setTimeout(function()
                    $("#loginPage").fadeOut();
                , 1000);
                // Create a smoother transition between pages

                $.get("./pages/game.html" ,function(data)
                    console.log(data);
                    $("#test").html(data);
                );

                setTimeout(function()
                    $('#gamePage').fadeIn();
                , 2000);
             else 
                userError.removeClass("hide");
            
        );

        newUser.val("");
    );

    // ===============================================
    // PLAYER VS PLAYER APPEND
    // ===============================================

    // Append player names to battle
    socket.on("event_new_user", function(data)
        playerOne = data.userOne;
        playerTwo = data.userTwo;
        $(".playerOne").append(playerOne);
        $(".playerTwo").append(playerTwo);
    );


    // ===============================================
    // MESSAGE BOX LOGIC
    // ===============================================
    var users           = $(".playersOnline"), // Area to append all users names
        messageForm     = $(".sendMessage"),
        messageBox      = $(".message"),
        chat            = $(".chat");

    // Display all the usernames in chat room area
    socket.on("usernames", function(data)
        var html ="";
        for(i=0 ; i < data.length; i++) 
            html += data[i] + "<br/>";
        
        users.html(html);
    );

    // On sumbit sends message to server to be fufilled
    messageForm.click(function(e)
        // Prevent sumbit button default
        e.preventDefault();
        socket.emit("send message", messageBox.val());
        messageBox.val('');
    );

    // Appends the new message from the user to the chat box
    socket.on("new message", function(data)
        console.log(data.user);
        chat.append("<b>" + data.user + ": </b>" + data.msg + "<br/>");
    ); 
)

;

编辑:

包含当前的pastebin:http://pastebin.com/WUzwuPrf

【问题讨论】:

【参考方案1】:

我看到的主要问题是代码中事件发生的顺序。 $.get 不应该影响 socket.io 的性能,而是问题在于您正在异步获取 html 代码,因此您的页面可能仅在获得 socket.io 事件后才获取 html 文件.

让我逐步介绍一下您的代码中运行的内容:

1.

var users           = $(".playersOnline"), // Area to append all  users names
    messageForm     = $(".sendMessage"),
    messageBox      = $(".message"),
    chat            = $(".chat");

以上行在页面加载时运行。但是,在页面加载时,您尚未加载 html,因此 jquery 将无法找到任何这些元素。注意:它不会出错,因为 jquery 可以很好地处理所有涉及 0 个元素的操作。

2。 表单提交后

// Display all the usernames in chat room area
socket.on("usernames", function(data)
    var html ="";
    for(i=0 ; i < data.length; i++) 
        html += data[i] + "<br/>";
    
    users.html(html);
);

这个事件很可能会在表单提交后立即执行(但在 html 加载之前)。这是因为 socket.io 使用的 websocket 非常快!同样的问题再次出现,因为 users 仍然是 0 元素的 jquery 选择器,因为 html 还没有在 DOM 中。

3.

    $.get("./pages/game.html" ,function(data)
        console.log(data);
        $("#test").html(data);
    );

最后,在其他一切运行之后,这很可能会最后触发。回调函数将设置页面上的 html 并将所有元素插入 DOM。但是,为时已晚,因为所有其他 socket.io 事件可能已经执行,页面上没有任何元素来放置所有数据。

TLDR: 对于 socket.io 事件,您应该确保您的服务器在您的页面准备好之前不会发送它们(也许将“新用户”事件分成“新用户”和'page ready' 事件),或者您可以全局存储数据并仅在 $.get 完成时将其放在页面上(不建议使用第二个选项,因为它仍然存在时间问题)。

确保如果您执行 var users = $(".playersOnline") 之类的操作,您只能在 $.get 更新页面后运行的代码中执行此操作(类似 users.html(html); 之类的操作也是如此)。我建议创建一个 function gamepage_ready()... 函数,该函数在插入 html 后由 $.get 调用,该函数负责将 socket.io 中的数据插入到页面中。

【讨论】:

我尝试将我所有的套接字代码放在一个名为 chatRoom() 的函数中,但是当我在 $.get 之后触发它时,套接字事件仍然不起作用。 好的,我已经创建了一个 pastebin。我现在所做的是创建了一个名为 d1 的变量。这存储了我的 ajax 调用,然后将加载 game.html。然后在我的提交功能下,我检查调用何时完成,然后我执行我的其他功能。我现在唯一遇到的问题是,如果可能的话,我希望它只在 sumbit 上加载 game.html 如果您需要在提交后加载game.html,那么您需要全局存储来自socket.io事件的数据以在html加载后插入页面或更改服务器延迟发送事件,直到它从浏览器获得加载 html 文件的 ok 之后。

以上是关于使用 $.get 调用文件时,socket.io 事件不起作用的主要内容,如果未能解决你的问题,请参考以下文章

尝试发出时,带有 Node.js 的 Socket.io 在路由文件中返回未定义

尝试实现 socket.io 通信时收到 GET 400。 Node.js、ELB、Route 53、CloudFront 和 s3

调用服务器时找不到socket.io

在 socket.io-client 中调用 IO 时出错,角度 8

使用 Express JS 路由中的 Socket.io

angular 4/socket.io 访问全局变量和函数调用