Node.js+Socket.io聊天项目:删除输入后‘typing...’提示未消失问题
问题描述
我正在开发一个基于Node.js和Socket.io的实时聊天项目,遇到如下问题:当在聊天框中输入内容后,未发送而是删除所有输入内容时,对方客户端仍持续显示‘typing...’提示。我无法定位代码中的错误位置,相关代码如下:
原Node.js代码
const express = require('express'); const socket = require('socket.io'); const app = express(); const server = app.listen(3000) app.use(express.static('public')) const io = socket(server); io.on('connection', (socket) => { console.log(socket.id) socket.on('chat', data => { io.sockets.emit('chat', data) }) socket.on('typing', data => { socket.broadcast.emit('typing', data) }) })
原前端JavaScript代码
const socket = io.connect('http://localhost:3000'); const sender = document.getElementById('sender'); const message = document.getElementById('message'); const submitBtn = document.getElementById('submitBtn'); const output = document.getElementById('output'); const feedback = document.getElementById('feedback'); submitBtn.addEventListener('click', () => { if (sender.value != '' && message.value != '') { socket.emit('chat', { message: message.value, sender: sender.value, }); sender.disabled = true; } }) socket.on('chat', data => { feedback.innerHTML = '' output.innerHTML += '<p><strong>' + data.sender + ' : </strong>' + data.message + '</p>' message.value = ''; }) message.addEventListener('keypress', () => { if (message.value.trim() != false) { socket.emit('typing', sender.value) } else { feedback.innerHTML = '' } }) socket.on('typing', data => { feedback.innerHTML = '<p>' + data + ' typing...</p>'; })
问题原因分析
- 事件监听范围不足:原代码用
keypress事件监听输入,该事件仅在按下可打印字符时触发,退格、删除等清空内容的操作不会触发最后一次判断,导致内容为空时无法通知对方停止显示typing提示。 - 判断逻辑错误:
message.value.trim() != false的写法有误,空字符串''和布尔值false比较时结果为true,导致内容为空时仍会触发typing事件。 - 缺少停止输入的通知机制:仅在本地清空自己的feedback,没有通过Socket.io通知其他客户端清空提示。
修复方案及修改后代码
1. 后端添加停止输入事件监听
在Node.js代码中新增stopTyping事件的处理,用于广播停止输入的状态给其他客户端:
const express = require('express'); const socket = require('socket.io'); const app = express(); const server = app.listen(3000) app.use(express.static('public')) const io = socket(server); io.on('connection', (socket) => { console.log(socket.id) socket.on('chat', data => { io.sockets.emit('chat', data) }) socket.on('typing', data => { socket.broadcast.emit('typing', data) }) // 新增停止输入事件 socket.on('stopTyping', () => { socket.broadcast.emit('stopTyping') }) })
2. 前端修改输入监听逻辑
- 替换
keypress为input事件,覆盖所有内容变更场景(退格、删除、粘贴等)。 - 修复判断逻辑,用
trimmedVal !== ''判断内容是否为空。 - 内容为空时发送
stopTyping事件通知服务器。 - 发送消息后也触发
stopTyping,避免发送后仍显示typing提示。 - 添加
stopTyping事件监听,清空对方的typing提示:
const socket = io.connect('http://localhost:3000'); const sender = document.getElementById('sender'); const message = document.getElementById('message'); const submitBtn = document.getElementById('submitBtn'); const output = document.getElementById('output'); const feedback = document.getElementById('feedback'); submitBtn.addEventListener('click', () => { if (sender.value != '' && message.value != '') { socket.emit('chat', { message: message.value, sender: sender.value, }); sender.disabled = true; // 发送消息后通知停止输入 socket.emit('stopTyping'); } }) socket.on('chat', data => { feedback.innerHTML = '' output.innerHTML += '<p><strong>' + data.sender + ' : </strong>' + data.message + '</p>' message.value = ''; }) // 用input事件监听所有内容变化 message.addEventListener('input', () => { const trimmedVal = message.value.trim(); if (trimmedVal !== '') { socket.emit('typing', sender.value) } else { // 内容为空时发送停止输入事件 socket.emit('stopTyping'); } }) socket.on('typing', data => { feedback.innerHTML = '<p>' + data + ' typing...</p>'; }) // 监听停止输入事件,清空提示 socket.on('stopTyping', () => { feedback.innerHTML = ''; })
内容的提问来源于stack exchange,提问作者prf00
相关产品推荐
相关产品推荐

