socket.io+html网页聊天室输入昵称时反复循环,不能正确返回信息

在输入昵称后输入信息会回到输入昵称的步骤:

img


且在启动服务器后未打开网页的情况下一直提示有用户连接:

img

var express = require('express');
const app = express();
const bodyParser = require('body-parser');

var http = require('http').Server(app);
var io = require('socket.io')(http);
var usocket = [];

app.use( bodyParser.json() );       // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  extended: true
})); 

app.use(express.static('public'))

// index page
app.get('/testGet', function(req, res) {    
  let firstName = req.query.firstName
  let surname = req.query.surname
  res.send(`
           <!doctype html>
           <head>
           <title>Test GET</title> 
           </head>
           <body>
<strong> First Name:</strong>${firstName} <br>
<strong> Surname:</strong>${surname}
           </body> 
           `);
});

io.on('connection', function(socket){
  console.log('a user connected')

  socket.on("join", function (name) {
    usocket[name] = socket
    io.emit("join", name)
  })

  socket.on("message", function (msg) {
    io.emit("message", msg) //将新消息广播出去
  })

});
app.listen(8080);
console.log('Server is listening on port 8080');

<!doctype html>
<html>

<head>
  <title>客户群聊界面</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: '微软雅黑'
    }

    #container {
      width: 100%;
      height: 1700px;
      background: #eee;
      position: relative;
      box-shadow: 40px 40px 110px #777;
    }

    .header {
      background: #25421ab0;
      height: 80px;
      color: #fff;
      line-height: 68px;
      font-size: 40px;
      padding: 0 20px;
    }


    body {
      width: 100%;
      background: #eee;
      position: relative;
      font: 60px;
    }

    form {
      background: #000;
      position: fixed;
      bottom: 0;
      width: 100%;
    }

    form input {
      border: 0;
      width: 80%;
      font-size: 40px;
    }

    form button {
      width: 20%;
      background: rgb(130, 224, 255);
      border: none;
      font-size: 40px;
    }

    #messages {
      list-style-type: none;
      margin: 0;
      padding: 0;
      font-size: 40px;
    }

    #messages li {
      padding: 5px 10px;
      font-size: 40px;
    }

    #messages li:nth-child(odd) {
      background: #eee;
    }
  </style>
  <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>

<body>
  <div class="header">
    <span style="float: left;">Chat room</span>
    <!--<span style="float: right;">14:21</span>-->
  </div>
  <ul id="messages"></ul>
  <form action="">
    <input id="m" placeholder="说点什么吧..." autocomplete="off" /><button>发送</button>
  </form>
</body>

<script src="/socket.io/socket.io.js"></script>
<script>
  var name = prompt("请输入你的昵称:");
  var socket = io()

  //发送昵称给后端,并更改网页title
  socket.emit("join", name)
  document.title = name + "的群聊"

  socket.on("join", function (user) {
    addLine(user + " 加入了群聊")
  })

  //接收到服务器发来的message事件
  socket.on("message", function (msg) {
    addLine(msg)
  })

  //当发送按钮被点击时
  $('form').submit(function () {
    var msg = $("#m").val() //获取用户输入的信息
    socket.emit("message", msg) //将消息发送给服务器
    $("#m").val("") //置空消息框
    return false //阻止form提交
  })

  function addLine(msg) {
    $('#messages').append($('<li>').text(msg));
  }
</script>

</html>

引用chatGPT作答,根据您提供的代码和问题描述,问题出现在聊天室中输入昵称的过程中。在代码中,当客户端连接到服务器时,会监听客户端发来的"join"事件,当收到该事件时,将用户名和客户端的socket对象保存在一个数组中,然后向所有客户端广播该用户加入聊天室的信息。而在聊天室中发送消息时,客户端会将消息内容发送到服务器,然后服务器再将消息广播给所有的客户端。

现在的问题在于,在聊天室中输入昵称时,反复循环且不能正确返回信息,在输入昵称后再输入信息无法发送,且会回到输入昵称的步骤,用户进入聊天室没有提示。这是因为在代码中使用了一个数组 usocket 来保存用户名和客户端的socket对象,但数组定义时没有使用 let 或 var,导致该数组被定义为一个全局变量,而不是一个局部变量,因此在多个客户端连接到服务器时,它们会共用这个全局变量,而互相干扰。

解决这个问题的方法是将 usocket 定义为一个局部变量,只在当前连接的客户端中保存该客户端的socket对象。具体地,可以将 usocket 定义为一个空对象,然后在每个客户端连接时,将用户名和socket对象作为一个键值对添加到 usocket 中。修改后的代码如下:

io.on('connection', function(socket){
  console.log('a user connected')

  var usocket = {}; // 定义局部变量 usocket

  socket.on("join", function (name) {
    usocket[name] = socket; // 添加一个键值对
    io.emit("join", name);
  })

  socket.on("message", function (msg) {
    io.emit("message", msg) //将新消息广播出去
  })

});

另外,您还提到用户进入聊天室没有提示的问题。如果您想要在用户进入聊天室时给出提示,可以在客户端连接到服务器后,通过向客户端发送一个事件来实现。修改后的代码如下:

io.on('connection', function(socket){
  console.log('a user connected')

  var usocket = {}; // 定义局部变量 usocket

  socket.on("join", function (name) {
    usocket[name] = socket; // 添加一个键值对
    io.emit("join", name);
  })

  socket.on("message", function (msg) {
    io.emit("message", msg) //将新消息广播出去
  })

  socket.emit("join", "欢迎来到聊天室"); // 发送欢迎消息
});

这样,在用户连接到服务器时,服务器会向该用户发送一个 "join" 事件,其中包含欢迎消息 "欢迎来到聊天室",从而给用户一个提示。