I am making a chatroom application using reactjs(socketIo) and nodeJs. When I emit the message from frontend to server, it gets emitted only once, but when I emit it back from server to frontend, It gets emitted multiple times.
Frontend Code:
function handleChat(event) {
event.preventDefault();
socket.emit("newMessage", { message: msg, user: props.user.name });
setMsg("");
}
socket.on("messageList", (list) => {
console.log(list.message);
var allMsg = messages
allMsg.push({message: list.message.message, name: list.message.user})
setMessages(allMsg);
})
In the code above newMessage is the handler for emitting the message from frontend to server and messageList is the handler for message from the server(which is the issue).
Backend Code:
namespace.forEach((ns) => {
io.of(`/${ns.name}`).on("connect", (socket1) => {
// console.log(ns.name, socket1.id);
socket1.on("name",(name)=>{
console.log(name);
})
socket1.on("newMessage", (message) => {
console.log(message);
io.of(`/${ns.name}`).emit("messageList",{message})
});
});
});
Related
I am trying to use callback function on the server when I emit to a room. In the room there is only 1 device that has a specific channel number. I can emit to it but can not get the callback to work.
server
socket.to(userId).emit('request-api', options, (response: any) => {
console.log(response);
});
client
socket.on('request-api', (arg1, callback) => {
console.log(arg1);
callback({
status: 'ok',
});
});
Is there a way that I can have the server to emit event and get callback. Nodejs project
I created private chat app using Socketio with nodejs server. i am saving chat messages to monogdb and sending back tom client but when i refresh page chat messages are disappearing but they are save d to db. Can anyone help me please?
CLient
useEffect(() => {
socket.on("connect", () => {
console.log("Connection established!");
});
socket.on("loggedin", () => {
console.log("you're logged in!");
setLoggedIn(true);
fetchOnlineUsers();
socket.on("newConnection", () => {
console.log("watch out! a new challenger appears!");
fetchOnlineUsers();
});
});
socket.on("message", (newMessage) => {
console.log("a new message appeared!", newMessage);
setChatHistory((chatHistory) => [...chatHistory, newMessage]);
});
}, []);
SERVER
socket.on("sendmessage", async({ message, room }) => {
const newMessage = new MsgModel({
text:message.text,
sender: message.sender,
socketId:message.socketId
});
newMessage.save().then(() => {
socket.to(room).emit('message', newMessage)
})
console.log("Message",newMessage);
// Emits only to people inside of the defined "room"
})
From what you've shared, I can only understand that you are sending messages to the receiver through socket, but when the user connects again to that particular room, are you fetching all previous messages from your mongo conversation document?
In order to receive messages that were sent previously, you need to fetch all messages associated to that room when the user first loads the page. You can create another API that fetches the records from where you previously stored your messages and list it for the user like you do when receiving the message socket trigger
So. Server sends event to every client in specific room on message submit for other clients to load messages, so they can see that new message. React client correctly receives, but loads messages in weird way. It renders page with no messages and after few miliseconds loads correctly. It cause very ugly blink.
Client socket.io code:
useEffect(() => {
loadRooms(userId).then(data => {
dispatch(setRoomsList(data))
})
loadMessages(roomId).then(data => {
dispatch(setMessageList(data))
});
socket.on('receive_message', data => {
dispatch(addNewMessage({id: data.id, content: data.message, roomId: data.room, userName: data.userName}));
console.log(messageList)
})
}, [dispatch, roomId, socket])
Client who sends message doesn't have this bug. On this client, axios request works correctly.
Submit message handler:
const handleMessageSubmit = e => {
e.preventDefault()
sendMessage(userName, currentMessage, roomId).then(data => {
loadMessages(roomId).then(data => {
dispatch(setMessageList(data))
socket.emit('send_message', {message: currentMessage, room: roomId});
})
setCurrentMessage('')
})
}
Loading message normally with that handler work just fine, but with socket.io it is bugged.
How messages are displayed in page:
{messageList.map(message =>
<div sx={{overflow: 'auto'}} key={message.id} style={{display: 'block', width: '70vw', marginTop: '5px', clear: 'both'}}>
<div style={{wordWrap: 'break-word'}} key={message.id}>{message.userName}: {message.content}</div>
</div>
)}
messageList is redux state, which I get using mapStateToProps
Socket.io on the server side:
io.on('connection', (socket) => {
let prevRoom = 1;
console.log("Users's id", socket.id)
socket.on('send_message', (data) => {
socket.to(data.room).emit('receive_message', data.message)
console.log("sent", data.message)
})
socket.on('join_room', (data) => {
socket.leave(prevRoom)
prevRoom = data;
socket.join(data)
console.log("joined")
})
} )
The idea behind sending data through web sockets is that you read it from message that you receive and then render. You don't do that here. You ignore the data in "receive_message" and call "loadMessages" that, I assume, loads full messages list from api. This extra call to api causes the ugly blink, but the code that resets messageList is not in question (probably in redux).
You need to get rid of extra api call and append the new message received via web socket to your existing message list
I am setting up a web socket server with socket.io and it seems like that messages are sent at least twice. Sometimes even trice. (very rarely even 4+ times) They are never sent once though. How should I setup my handlers or my client code so every message is received exactly once all the time?
My client is in swift and my server in node.js. I am running Ubuntu 16.04 on the server itself.
Node.js:
// Here is an array of all connections to the server
var connections = {};
io.sockets.on('connection', newConnection);
function newConnection(socket) {
socket.on('add-user', function(user) {
connections[user.id] = {
"socket": socket.id
};
});
socket.on('chat-message', function(message) {
console.log(message);
if (connections[message.receiver]) {
console.log("Send to: " + connections[message.receiver].socket);
// Here are some varients of the emit command. Seems like they all do the same
//io.sockets.connected[connections[message.receiver].socket].emit("chat-message", message);
//io.to(connections[message.receiver].socket).emit("chat-message", message);
socket.broadcast.to(connections[message.receiver].socket).emit("chat-message", message);
} else {
console.log("Send push notification")
}
});
//Removing the socket on disconnect
socket.on('disconnect', function() {
console.log("The client disconnected");
for (var id in connections) {
if (connections[id].socket === socket.id) {
delete connections[id];
}
}
})
}
The "console.log(message);" in the messages handler is only called once. That's the confusing part for me. If the handler is called twice, why is this only printed once? Still, on the handler in my swift code, the handler for received messages is called multiple times.
I have a react native 0.59 app with nodejs 10.2 as backend. The socket.io 2.2.0 running on a server and it is 2.1.1 running on the app client. Here is the socket related code:
Nodejs server:
All socket.io related code is in the index.js file:
io.on('connection', (socket) => {
console.log("socket.id : ", socket.id);
socket.on('message', (msg) => {
console.log("msg received by server socket : ", msg);
});
console.log("Socketio server is initialized");
//disconnect
socket.on('disconnect', async function() {
try {
await SocketList.update({
active: false
}, {
where: {socket_id: isocket.id}
});
} catch(err) {
console.log("err in false socket id", socket.id);
}
console.log('disconnected event');
});
});
A listener for message is implemented.
React Native App:
The socket.io client used is 2.1.1. The socket is initiated in App.js and pass to Chat component. In the Chat component, connect is made with the socket to the server and emit a message:
App.js:
//socket.io
const socket = io(GLOBAL.BASE_URL, {
transports: ['websocket'],
jsonp: false
});
let props = {
eventId: "",
user: ""
};
const ChatWithSocket = (props) => (<Chat {...props} socket={socket} />)
//create the navigator
const navigator = createStackNavigator(
{
Event: Event,
Chat: {
screen: ChatWithSocket,
}
}, {
initialRouteName: "Event"
}
);
Component Chat.js:
When user enter a chat message and click send, The socket fires up the connect and emit a message with the message entered by the user:
_onSend(messages = []) {
console.log("socket.io in chat _onSend : ", this.props.socket.id);
this.props.socket.connect();
this.props.socket.on('connect', () => {
socket.emit("message", {msg: messages[0].text});
});
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, messages),
}))
}
The problem is after the chat message is sent from the app, there is no response from the server and the following socket listener code is not executed:
socket.on('message', (msg) => {
console.log("msg received by server socket : ", msg);
});
Here is the console output (portion) on Nodejs server:
Listening on port 3000...
Executing (default): SELECT 1+1 AS result
DB connection has been established successfully.
socket.id : U0Vm-O5ainh-IRusAAAA
Socketio server is initialized
err in false socket id U0Vm-O5ainh-IRusAAAA
disconnected event
socket.id : 7qo9ncTog0dhPfL6AAAB
Socketio server is initialized
The initial socket connection was closed and the socket 7qo9ncTog0dhPfL6AAAB is initiated again.
Here is the app console output showing 2 messages have been sent by client 7qo9ncTog0dhPfL6AAAB which matches the socket.id on the server:
4-14 22:21:19.034 26574 26634 I ReactNativeJS: 'socket.io in chat _onSend : ', '7qo9ncTog0dhPfL6AAAB'
04-14 22:21:24.286 26574 26634 I ReactNativeJS: 'socket.io in chat _onSend : ', '7qo9ncTog0dhPfL6AAAB'