我正在开发一个实时聊天在nodejs和react和socket io。从理论上讲,聊天是正常的,但问题是,只有当接收者也发送消息时,发送者的消息才会出现在屏幕上。
例:我有浏览器1和浏览器2。每次浏览器1发送消息时,这些消息都会出现在它的屏幕上,但是只有当浏览器2发送消息时,这些消息才会出现在浏览器2的屏幕上。const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const dotenv = require('dotenv')
const app = express();
const mongoose = require('mongoose');
const http = require('http');
const server = http.createServer(app);
const { Server } = require('socket.io');
const io = new Server(server, {
cors: {
origin: ['http://localhost:3000'],
}
});
dotenv.config();
const nameRoutes = require('./routes/nameRoutes');
app.use(express.json());
app.use(cors());
app.use(bodyParser());
app.use('/name', nameRoutes);
app.use('/', (req, res) => {
res.status(200).json({ msg: 'API IS ALIVE!' });
})
let messages = []
io.on('connection', (socket) => {
socket.on('send-message', (data) => {
messages.push(data);
socket.emit('message-from-server', messages);
console.log(messages);
})
});
async function connection () {
const uri = process.env.MONGO_URI;
const port = process.env.PORT;
try {
await mongoose.connect(uri);
console.log('Connected to database');
server.listen(port, () => {
console.log(`Listening on port ${port}`)
});
} catch (err) {
console.log(err);
}
}
connection();
module.exports = app;
反应/socketio
import * as C from './styles';
import { io } from 'socket.io-client';
import { useNavigate } from 'react-router-dom';
import { useEffect, useState } from 'react';
const Chat = () => {
const navigate = useNavigate();
const [message, setMessage] = useState('');
const [chatMessages, setChatMessages] = useState([]);
const [socket, setSocket] = useState(null);
useEffect(() => {
setSocket(io("http://localhost:3010"));
}, []);
useEffect(() => {
if (socket) {
socket.on('message-from-server', (data) => {
setChatMessages(data);
})
}
}, [socket])
const handleSendMessage = () => {
if (message) {
socket.emit('send-message', { message });
setMessage('');
}
}
const handleExitChat = () => {
navigate('/');
}
return (
<C.Container>
<C.MessagesChat>
<h2>Messages</h2>
</C.MessagesChat>
{chatMessages.map(text => {
return (
<C.Messages>
<p>{text.message}</p>
</C.Messages>
)
})}
<C.MessageText>
<textarea
name=""
id=""
cols="30"
rows="10"
placeholder='Digite sua mensagem...'
value={message}
onChange={(e) => setMessage(e.target.value)}
></textarea>
<button onClick={handleSendMessage}>Enviar</button>
</C.MessageText>
</C.Container>
)
}
export default Chat;
你正在使用
socket.emit('message-from-server', messages);
尝试使用io.emit
,它向所有连接的套接字广播。套接字。Emit用于仅向被调用的套接字发送消息。在本例中,这意味着第一个发送消息的套接字。如果你只是想通知单个套接字正确处理了某些事情等,这可能很有帮助,但当你想通知其他用户套接字的活动时,它就没有用了。
编辑:这里有一个文档的链接,描述你的各种emit选项:https://socket.io/docs/v4/broadcasting-events/
服务器端代码应该是这样的:
io.on('connection', (socket) => {
// Define our routes first, but note the key new emit below this listener
socket.on('send-message', (data) => {
messages.push(data);
// Notify all connected users each time a message is posted
io.emit('message-from-server', messages);
console.log(messages);
}
// THIS IS NEW
// This is your initial load, to get the messages when you open the page.
socket.emit('message-from-server', messages);
}
请注意我在侦听器中使用的io.emit
和第一次连接时使用的socket.emit
之间的差异。