#javascript #node.js #server #socket.io
Вопрос:
Я работаю над простым приложением для чата, которое изначально было разветвлено из репозитория GitHub. Это работает, но есть ошибка, которая возникает случайным образом и останавливает запуск приложения.
Код на стороне сервера
const path = require('path');
const http = require('http');
const express = require('express');
const socketio = require('socket.io');
const formatMessage = require('./utils/messages');
const {
userJoin,
getCurrentUser,
userLeave,
getRoomUsers
} = require('./utils/users');
const app = express();
const server = http.createServer(app);
const io = socketio(server);
// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
const botName = 'CCBot';
v = process.env;
// Run when client connects
io.on('connection', socket => {
socket.on('joinRoom', ({ token, username, room }) => {
console.log(token, username, room)
if (token == v.TOKEN_1){username = v.N_1}
else if (token == v.TOKEN_2){username = v.N_2}
else if (token == v.TOKEN_3){username = v.N_3}
else{
socket.emit("redirect"); return
}
const user = userJoin(socket.id, username, room, token, false);
socket.join(user.room);
// Welcome current user
socket.emit('message', formatMessage(botName, 'Welcome!'));
// Broadcast when a user connects
socket.broadcast
.to(user.room)
.emit(
'message',
formatMessage(botName, `${user.username} has joined the chat!`, 'green')
);
// Send users and room info
io.to(user.room).emit('roomUsers', {
room: user.room,
users: getRoomUsers(user.room)
});
});
// Listen for chatMessage
socket.on('chatMessage', (msg) => {
const user = getCurrentUser(socket.id)
console.log(user)
//The error originates on the below line
io.to(user.room).emit('message', formatMessage(user.username, msg, )); //The error occurs here
});
socket.on('userLeave', (id) => {
const user = getCurrentUser(id)
console.log(user)
socket.emit("sendMessages", user)
})
// Runs when client disconnects
socket.on('disconnect', () => {
const user = userLeave(socket.id);
if (user) {
io.to(user.room).emit(
'message',
formatMessage(botName, `${user.username} has left the chat.`, "red")
);
// Send users and room info
io.to(user.room).emit('roomUsers', {
room: user.room,
users: getRoomUsers(user.room)
});
}
});
});
const PORT = process.env.PORT || 3000;
server.listen(300, () => console.log(`Server running on port 3000`));
Функции Util
const users = [];
// Join user to chat
function userJoin(id, username, room, auth, admin ) {
const user = { id, username, room, admin };
users.push(user);
return user;
}
// Get current user
function getCurrentUser(id) {
return users.find(user => user.id === id);
}
// User leaves chat
function userLeave(id) {
const index = users.findIndex(user => user.id === id)
if (index !== -1) {
return users.splice(index, 1)[0];
}
}
// Get room users
function getRoomUsers(room) {
return users.filter(user => user.room === room);
}
module.exports = {
userJoin,
getCurrentUser,
userLeave,
getRoomUsers
};
function formatMessage(username, text, color) {
return {
username,
text,
time: moment().tz("My Timezone here.").format('h:mm a'),
color
};
}
module.exports = formatMessage;
Client Side
let notif = undefined;
// Get username and room from URL
const { username, room, token, t2 } = Qs.parse(location.search, {
ignoreQueryPrefix: true,
});
listUsers = [];
const socket = io();
// Join chatroom
socket.emit('joinRoom', { username, room, token });
// Get room and users
socket.on('roomUsers', ({ room, users }) => {
outputRoomName(room);
outputUsers(users);
});
socket.on("redirect", () => {
try { window.location = "wrongpassword.html" }
catch (e) {
window.location = "about:blank"
}
})
// Message from server
socket.on('message', (message) => {
console.log(message);
outputMessage(message);
// Scroll down
chatMessages.scrollTop = chatMessages.scrollHeight;
});
socket.on("sendMessages", user => {
banned.push(user.username)
socket.emit("BAN_ALERT")
})
// Message submit
chatForm.addEventListener('submit', (e) => {
e.preventDefault();
// Get message text
let msg = e.target.elements.msg.value;
msg = msg.trim();
if (!msg) {
return false;
}
// Emit message to server
socket.emit('chatMessage', msg);
// Clear input
e.target.elements.msg.value = '';
e.target.elements.msg.focus();
});
function enableNotif(){
notif = true;
}
function disableNotif(){
notif = false;
}
// Output message to DOM
function outputMessage(message) {
if (message.text == ".clear" || message.text ==
".c") {
try {
document.querySelector(".chat-messages").innerHTML = ""
return
}
catch (e) {
window.location.reload(true)
return
}
}
else if (message.text == ".exit" || message.text == ".e"){
location = "about:blank"
}
else if (message.text == ".users"){
console.log(userList)
div = document.createElement('div');
div.classList.add('message');
const p = document.createElement('p');
p.classList.add('meta');
p.innerText = "CCBot";
p.innerHTML = ` <span>${message.time}</span>`;
div.appendChild(p);
const para = document.createElement('p');
para.classList.add('text');
para.innerText = listUsers;
color = "black";
if(color){para.style.color = color}
else{para.style.color = "black"}
div.appendChild(para);
document.querySelector('.chat-messages').appendChild(div);
}
else {
const div = document.createElement('div');
div.classList.add('message');
const p = document.createElement('p');
p.classList.add('meta');
p.innerText = message.username;
p.innerHTML = ` <span>${message.time}</span>`;
div.appendChild(p);
const para = document.createElement('p');
para.classList.add('text');
para.innerText = message.text;
color = message.color;
if(color){para.style.color = color}
else{para.style.color = "black"}
div.appendChild(para);
document.querySelector('.chat-messages').appendChild(div);
if (notif) {
var audio = new Audio('./media/notif.mp3');
console.log(audio)
audio.play();
}
}
}
// Add room name to DOM
function outputRoomName(room) {
roomName.innerText = room;
}
// Add users to DOM
function outputUsers(users) {
userList.innerHTML = '';
users.forEach((user) => {
const li = document.createElement('li');
li.innerHTML = `${user.username} <br><hr>`;
li.style = "cursor:pointer;"
userList.appendChild(li);
listUsers.push(li.innerText)
});
}
//Prompt the user before leave chat room
document.getElementById('leave-btn').addEventListener('click', () => {
const leaveRoom = confirm('Are you sure you want to leave the chatroom?');
if (leaveRoom) {
window.location = '../index.html';
} else {
}
});
Ошибка
TypeError: Cannot read property 'room' of undefined
at Socket.socket.on.msg (/home/duck/server.js:51:16)
at Socket.emit (events.js:198:13)
at /home/duck/node_modules/socket.io/lib/socket.js:528:12
at process._tickCallback (internal/process/next_tick.js:61:11)
/home/duck/server.js:51
io.to(user.room).emit('message', formatMessage(user.username, msg));
^
В репо уже открыта эта проблема, но ответа на нее нет.
Я не уверен, почему возникает ошибка.
Заранее спасибо.
P. S, Пожалуйста, игнорируйте все, что связано с запретом/удалением пользователей.
Комментарии:
1. Если пользователь, который не прошел надлежащую проверку подлинности (= вы не можете найти текущий объект пользователя), отправляет сообщение, вам следует просто не обрабатывать его, вместо того, чтобы аварийно завершать работу…
2. @CherryDT
if (!(user)){return}
Это то, что ты предлагаешь?