The "stanza" event is not fired. But messege is sending - node.js

Below is code for react:
import React, {useEffect} from 'react'
import { BoshClient } from "xmpp-bosh-client/browser";
const dummyMessages = [
{
id: 'abcdef',
isSender: true,
message: 'Heelo'
},
{
id: 'bcdef',
isSender: false,
message: 'Hi'
}
]
const USERNAME = "test_user1#example.com";
const PASSWORD = "12345678";
const URL = "";
const client = new BoshClient(USERNAME, PASSWORD, URL);
const messege_box = document.querySelector('#msg-field');
client.on("error", (e) => {
console.log("Error event");
console.log(e);
alert(e);
});
client.on("*", (e) => {
console.log(e);
});
client.on("online", () => {
console.log("Connected successfully");
client.sendMessage('test_user2#example.com', 'this is test', 'chat')
});
client.on("ping", () => {
console.log('Ping received at ${new Date()}');
});
client.on("stanza", (stanza) => {
console.log('Stanza received at ${new Date()}');
console.log('stanza', stanza);
let messageObj = {
isSender: false,
message: 'message' //Chaqnge this
}
setMessages(prevValue => [...prevValue, messageObj])
//his is incoming message
//const [messages, setMessages] = React.useState([]);
});
client.on("offline", () => {
console.log("Disconnected/Offline");
});
client.connect();
The problem is "stanza" event is not fired although the "online" event is fired and sucessfully connected and can send the message to the other client which is working fine, only issue is "stanza" event is not fired.
Can any one shed some lights on it?
Thank You in Advance.

Related

Timeout on socket io listeners

I saw this documentation for socketio emit() with timeout implementation
https://socket.io/docs/v3/emitting-events/#acknowledgements
I am implementing it on listeners.
I have a code as follows:
app.post('/submitmessage', async (req, res) => {
const reqBody = req.body;
const roomId = reqBody['custom-roomid'];
socketConnection.join(roomId);
const hasRoom = io.sockets.adapter.rooms.has(roomId);
if (hasRoom) {
io.to(roomId).emit("room created", {
roomId: roomId,
data: reqBody.sendData
});
}
// this emit has a listener on client displaying a modal with message and buttons
// like SAVE, OK, CANCEL
io.to(roomId).emit("question", {
data: reqBody.sendData,
browserId: reqBody.browserId,
sessionId: reqBody.sessionId,
roomId: roomId
});
let reply = '';
// this listener is listening for which button was clicked by the user on the
// client passed on by variable warres
socketConnection.on('return-warning-response', ({ warres }) => {
reply = warres;
});
// waiting for 2 secs
await sleep(20000);
socketConnection.leave(roomId);
if (reply === '') {
res.sendStatus(404);
}
res.send(reply);
});
When I implement it on the listener like below:
socketConnection.on('return-warning-response', ({ warres }), withTimeout(() => {
console.log("success!");
}, () => {
console.log("timeout!");
}, 20000));
It gives error: UnhandledPromiseRejectionWarning: ReferenceError: warres is not defined
Is there an alternative for a timeout functionality on listeners?

Socket.io event works randomly

What I'm trying to do is to emit a event based on the progress of my jobs. It's working in the Gateway(proxy) side, the logs appear, etc, but when I'm consuming the event on the front-end, sometimes it works, sometimes not, and it throws 'ping timeout' error in the console. If I restart the nodejs service a few times it works.
I'm open to ideas of alternative ways to implement this feature.
SocketController
export default class SocketController {
socket: any;
interval: any;
instance: any;
queue: any;
constructor(server) {
// Creating Websocket connection
this.instance = new Server(server, {
cors: { origin: process.env.FRONTEND_URL },
path: "/socket.io/"
});
this.socket = null;
this.queue = null;
this.instance.on("connection", (socket) => {
let connectedUsersCount =
Object.keys(this.instance.sockets.sockets).length + 1;
let oneUserLeft = connectedUsersCount - 1;
console.log("New client connected ", connectedUsersCount);
// Assign socket to the class
this.socket = this.socket == null ? socket : this.socket;
/*
if (this.interval) {
clearInterval(this.interval);
}
*/
// initialize Queue
this.queue = this.queue === null ? new QueueService(socket) : this.queue;
socket.on("disconnect", () => {
console.log("Client disconnected ", oneUserLeft);
// clearInterval(this.interval);
});
});
}
QueueService
export default class QueueService {
channels: any;
socket: any;
constructor(socket: any) {
this.channels = ["integrationProgress", "news"];
this.socket = socket;
integrationQueueEvents.on("progress", (job: any) => {
console.log("Job Progressing", job);
this.socket.emit("integrationProgress", { status: true, data: job.data })
});
integrationQueueEvents.on("active", ({ jobId }) => {
console.log(`Job ${jobId} is now active`);
});
integrationQueueEvents.on("completed", ({ jobId, returnvalue }) => {
console.log(`${jobId} has completed and returned ${returnvalue}`);
this.socket.emit("integrationComplete", {
status: true,
message: returnvalue
});
});
integrationQueueEvents.on("failed", ({ jobId, failedReason }) => {
console.log(`${jobId} has failed with reason ${failedReason}`);
this.socket.emit("integrationProgress", {
status: false,
message: failedReason
});
});
}
}
Front-End
const socket = io(process.env.GATEWAY_URL, {
path: "/socket.io/"
});
socket.on("connect_error", (err) => {
console.log(`connect_error due to ${err.message}`);
socket.connect();
});
socket.on("disconnect", (socket) => {
console.log(socket);
console.log("Client disconnected ");
});
socket.on("connect", (socket) => {
console.log("Client Connected ");
console.log(socket);
});
socket.on("integrationProgress", async (socket) => {
try {
console.log(`Progress: ${socket.data}`);
updateJob(socket.data);
} catch (err) {
console.log(err);
}
});

Socket.io and React: Warning: Can't perform a React state update on an unmounted component

I am a relative newcomer to React and implementing a chat app with react, socket.io, and node.
When the user is chatting with someone, he would connect to a socket. It works fine, but if the user leaves to another page, and RE-ENTERS the same chat again, a second socket is connected(bad), and I get the "Can't perform a React state update on an unmounted component" error.
I did implement code to have socket leave the room (on the second useEffect), if the user leaves the page. But that doesn't seem to work.
Thanks in advance,
Error:
Partial React frontend code:
useEffect(() => {
socket.emit("enter chatroom", { conversationId: props.chatId });
setChatId(props.chatId);
getMessagesInConversation(props.chatId, (err: Error, result: any) => {
if (err) {
setCerror(err.message);
} else {
setMessages(buildMessages(result.messages).reverse());
}
});
socket.on("received", (data: any) => {
setMessages((messages: any) => {
console.log("messages");
console.log(messages);
return [...messages.slice(-4), ...buildMessages(data.newMsg)];
});
});
}, []);
useEffect(() => {
return () => {
socket.emit("leaveChatroom", {
conversationId: chatId,
});
};
}, [chatId]);
simplified nodejs code
private ioMessage = () => {
this._io.on("connection", (socket) => {
console.log("socket io connected");
const socketUser = socket.request.user;
socket.on("enter chatroom", (data) => {
const room_status = Object.keys(socket.rooms).includes(
data.conversationId
);
if (!room_status) { // should only join if socket is not already joined.
socket.join(data.conversationId);
}
});
socket.on("leaveChatroom", (data) => {
socket.leave(data.conversationId);
});
socket.on("chat message", async (msg) => {
const database = getDB();
const newMessage = {
...msg,
createdAt: Date.now(),
};
await database.collection("message").insertOne(newMessage);
const messages = await database
.collection("message")
.find({ conversationId: msg.conversationId })
.toArray();
this._io.to(msg.conversationId).emit("received", {
newMsg: [messages[messages.length - 1]],
});
});
socket.on("disconnect", (socket) => {
delete this._users[socketUser.userId];
console.log("--- disconnect : ", socketUser);
console.log("--- active users: ", this._users);
});
});
};
detailed error log:

Can not emit event with socketid

I am trying to write an integration test for socket io. I am using try-catch for server event when the error is catched I emit an event for the client to handle the error
io.of('/rooms').on('connection', socket => {
const socketId = socket.id;
console.log('server socketid', socketId);
const userRepository = getCustomRepository(UserRepository);
const conversationToUserRepository = getCustomRepository(ConversationToUserRepository);
socket.on('initGroupChat', async (users_id, fn) => {
try {
const [user, listConversationToUser] = await Promise.all([
userRepository.findOne({
where: {
users_id,
},
}),
conversationToUserRepository.find({
where: {
users_id,
},
}),
]);
if (!user) {
throw new NotFoundError('User not found with id: ' + users_id);
}
console.log(2);
user.socket_id = socket.id;
await userRepository.save(user);
for (const item of listConversationToUser) {
socket.join(item.conversation_id.toString());
}
fn('init group chat success');
} catch (error) {
io.to(socketId).emit('error', errorHandlerForSocket(error));
console.log(10);
}
});
});
but on the socket client, nothing happens. here is the code socket client:
it.only('Init Group Chat with error', done => {
socket = io.connect(`http://localhost:${env.app.port}/rooms`, {
transports: ['websocket']
});
const id = 11111;
socket.emit('initGroupChat', id, (response: any) => {
console.log('response', response);
});
socket.on('error', (error: any) => {
console.log('error3', error);
done();
});
});
on the error event, the console.log did not show on the terminate. it didn't catch the event I emit on the server.
can anyone help me fix this issue
Every time the client Refresh socketId changes.
Server :
io.emit("send_to_client", {
userId: 112233,
data: "Hello user 112233"
});
Client :
var userLogin = 112233;
socket.on("send_to_client", function(res) {
if(res.userId === userLogin)
//somethingElse
});

Why isn't my react client not receiving emitted messages?

im building a chat app using express and react and socket.io, and everything works, except that when I emit message from my server, it doesn't catch it in the client. Why is that? My code is:
index.js (server)
const io = require('socket.io')(server);
io.on('connection', socket => {
socket.on('join-room', data => {
console.log(`Joining room ${data.room}`);
socket.join(data.room);
});
socket.on('leave-room', data => {
console.log(`Leaving room room ${data.room}`);
socket.leave(data.room);
});
socket.on('new-message', data => {
console.log(`Sending message to room ${data.room}`);
socket.to(data.room).emit('new-message', data.message);
});
});
JoinRoom.js (react)
useEffect(() => {
socket.on('new-message', data => {
console.log('getting new message');
setMessages([...messages, data]);
});
}, [messages]);
useEffect(() => {
socket.emit('join-room', { room: id });
async function fetchData() {
const response = await req.get('/api/room/' + id);
setRoom(response.data);
const _messages = await req.get('/api/messages/' + id);
setMessages(_messages.data.docs);
}
fetchData();
}, [id]);
const send = e => {
e.preventDefault();
socket.emit('new-message', {
room: id,
message: newMessage
});
const data = {
message: newMessage,
user: 'Mikolaj',
roomId: id
};
req.post('/api/messages/send', data);
setNewMessage('');
};

Resources