Это хорошее начало.То, что я предложил бы сделать, это сделать это немного более управляемым событием.Чтобы сделать это, вы хотите добавить сокеты в комнату, когда они соединяются.Сколько комнат и как их разделить, будет зависеть от вашего приложения, но я продемонстрирую основную идею.
Во-первых, когда сокет подключается к вашему серверу, добавьте этот сокет в комнату и испуститеистория чата немедленно.
io.on('connection', async (socket) => {
socket.user = socket.request.session.user;
socket.join('chat');
try {
const messages = await Message.find({});
socket.emit('history', messages);
} catch (err) {
// Handle this error properly.
console.error(err);
}
});
Затем, позже, когда вы получите сообщение, вы захотите сохранить это сообщение и отправить его во все сокеты вашей комнаты чата.
socket.on("sendMessage", (msg, callback) => {
const message = new Message({ message: msg, sender: socket.user });
message.save(function(err) {
if (err) {
return callback(err);
}
io.to('chat').emit('message', message);
});
});
Наконец, на стороне клиента вы захотите прослушать событие истории.Получив его, вы захотите очистить текущую историю чата и заменить ее тем, что сообщает сервер.Возможно, это будет выглядеть примерно так:
socket.on('history', (messages) => {
this.setState({ messages });
});
Вы также захотите прослушать это событие message
, но с этим событием вы только добавите сообщение в свою историю.Это может выглядеть примерно так:
socket.on('message', (message) => {
this.setState({ messages: [ ...messages, message ] });
});
Слово предупреждения, если, когда вы сообщаете серверу о новом сообщении, не добавляйте его в массив состояний messages
, пока не получите событие message
.Если вы сделаете это, вы заметите двойные сообщения.Например, это может выглядеть примерно так:
onSendMessage(evnt) {
evnt.preventDefault();
socket.emit("sendMessage", msg);
this.setState({ msg: "" });
}
Примечание : Получив некоторую обратную связь от OP, я хотел добавить раздел о том, куда поместить обработчики событий, прикрепленные к сокету.(т.е. все socket.on
с).Я предлагаю добавить этот код в файл, который определяет схему Message
внизу файла в обратном вызове io.on('connection')
.Например,
const Message = new mongoose.Schema({/*...*/});
io.on('connection', (socket) => {
// Everything else I wrote above...
socket.on('sendMessage', (msg, callback) => {
// ...
});
});
На стороне клиента обработчики событий, вероятно, будут зарегистрированы при подключении компонента чата.Например,
class ChatComponent extends React.Component {
componentDidMount() {
this.socket = io('https://your-server-or-localhost/');
this.socket.on('history', (messages) => {
// See above...
});
}
}