用户离开聊天室没有提示
在输入昵称后输入信息会回到输入昵称的步骤,可能是每次输入信息并点击发送后就会刷新页面:
且在启动服务器后未打开网页的情况下一直提示有用户连接:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var usocket = {};
const express = require('express');
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile(__dirname + '/public/Introduction.html');
});
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) //将新消息广播出去
})
});
http.listen(8080, function() {
console.log('listening on *: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>
测试了题注代码视乎没问题,node代码部分改成了下面这样,用题注测试的链接服务器时会404.
新创建一个新的域名用于socket.io的转发,这样子只需要配置/路径转发就行,同时设置websocket升级请求头
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
对于socket.io和html网页聊天室中输入昵称时反复循环且无法正确返回信息的问题,可以采取以下措施进行优化:
1.前端代码中使用debounce或throttle函数来限制输入昵称时频繁触发emit事件的问题;
2.前端代码中增加校验逻辑,防止用户输入空白昵称或重复昵称等问题;
3.后端代码中增加判断逻辑,防止给自己发送消息或向不存在房间发送消息等问题;
4.对于用户离开聊天室的情况下,可以在前端代码中触发emit事件通知后端,后端再通过广播事件向其他用户发送提示信息,提示该用户已离开;
5.对于服务器启动但是网页未打开的情况下停止提示有用户连接的信息,可以在后端代码中增加判断逻辑,判断socket连接的数量是否为0,如果为0则不做处理。
以下是一组基于以上措施的示例代码:
前端代码:
let inputTimer = null;
const inputElem = document.querySelector('#nickname-input');
// debounce函数
function debounce(func, wait) {
return function() {
clearTimeout(inputTimer);
inputTimer = setTimeout(() => {
func.apply(this, arguments);
}, wait);
};
}
inputElem.addEventListener('input', debounce(() => {
const nickname = inputElem.value.trim();
if (nickname) {
socket.emit('setNickname', nickname);
}
}, 500));
socket.on('nicknameSet', (nickname) => {
// 显示昵称设置成功提示
});
socket.on('nicknameRepeat', () => {
// 显示昵称重复提示
});
socket.on('messageReceived', (from, message) => {
// 显示聊天信息
});
window.addEventListener('beforeunload', () => {
socket.emit('leaveRoom');
});
socket.on('userLeft', (nickname) => {
// 显示用户已离开提示
});
后端代码:
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require('socket.io');
const io = new Server(server);
let nicknameSet = false;
// 监听连接
io.on('connection', (socket) => {
if (nicknameSet) { // 防止重复设置昵称
socket.emit('nicknameRepeat');
return;
}
// 监听设置昵称
socket.on('setNickname', (nickname) => {
if (!nickname) { // 检查空白昵称
return;
}
nicknameSet = true;
socket.nickname = nickname;
socket.emit('nicknameSet', nickname);
socket.broadcast.emit('userJoined', nickname);
});
// 监听发送聊天信息
socket.on('sendMessage', (message) => {
if (nicknameSet && message) {
io.emit('messageReceived', socket.nickname, message);
}
});
// 监听离开聊天室
socket.on('leaveRoom', () => {
if (nicknameSet) {
io.emit('userLeft', socket.nickname);
}
});
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
为了更好地帮助您解决问题,您可以提供以下信息: