Socketio emit and on is not working properly in NodeJS - node.js

Socket io.on is not working in NodeJS.
Front End - Angular 14x
socket io version - "socket.io-client": "^4.5.4",
BackEnd - Nodejs 14x
socket.io version - "socket.io": "^4.5.4",
FrontEnd Code -
import SocketClient from 'socket.io-client';
export class Customer_FileUpload implements OnInit {
#Input() io = SocketClient(environment.url, {
autoConnect: true
})
submitRequest() {
this.shared.submitRequest(data).subscribe({
next: (response) => {
const result = JSON.parse(JSON.stringify(response));
console.log(result);
this.io.emit('emit-data', "I am good");
this.io.on('data2', (msg) => {
console.log('message: ' + JSON.stringify(msg));
});
},
error: (error) => {
console.log(error);
}
})
}
}
Backend Code -
index.js
const express = require('express');
const bodyparser = require('body-parser');
const cors = require('cors');
const fileUpload = require('express-fileupload');
const http = require('http');
const { RealTime } = require('./utils/socket');
const socket = new RealTime();
const app = express();
app.use(cors())
app.options('*', cors());
app.use(bodyparser.json({limit: '5mb', extended: true}))
app.use(bodyparser.urlencoded({limit: '5mb', extended: true}))
const authRoutes = require('./routes/authRoutes');
const apiRoutes = require('./routes/routes');
// For File Upload
app.use(fileUpload({
limits: { fileSize: 5 * 1024 * 1024 },
}));
app.use('/auth', authRoutes);
app.use('/user', apiRoutes);
//Capture All 404 errors
app.use(function (req,res,next){
res.status(404).send('Error - Unable to find the requested resource!');
});
app.use((req, res, next) => {
req.socket.on('error', () => {});
next();
});
const server = http.createServer(app);
socket.intialized_connection(server);
socket.init();
module.exports = server;
Socket.js
let io = null;
class RealTime {
constructor() {
if (io) return io;
io = this;
return io;
}
intialized_connection(httpServer) {
return (io = require('socket.io')(httpServer, {
cors: {
origin: '*',
// methods: ['GET', 'POST', 'PUT', 'DELETE'],
},
}));
}
init() {
io.on("connection", function (socket) {
console.log("A user connected");
//Whenever someone disconnects this piece of code executed
socket.on('disconnect', function () {
console.log('A user disconnected');
});
});
}
getIO() {
if (!io) {
throw new Error('Socket.io is not initialized');
}
return io;
}
sendEvents(event, data) {
this.getIO().emit(event, data);
}
receivedEvents(event) {
console.log(event);
this.getIO().on(event, function(data) {
console.log("I am emiiting here, ")
console.log(data)
});
}
}
module.exports = {
RealTime
};
Controller.js
exports.submitRequest = async(req, res) => {
socket.receivedEvents('emit-data');
socket.sendEvents("data2", {
message: "hello from nodejs controller"
});
res.json("done");
}
I have 2 issues here. Issues are ---
socket.receivedEvents -- Is not working, Not getting any error message, Neither in the client side not server side.
socket.sendEvents, It is working fine, in the client side, when we click second time. Attach the screenshot below.
First Time when we click on the submit button --
First time when we click on the submit
Second Time when we click on the submit button --
Second time when we click on the submit
Third Time when we click on the submit button --
Getting 2 times the same result.
Third time when we click on the submit
Any idea what I am doing wrong?
Can you please give me these 2 solution's problem?

Related

Socket.io server not runnning

i'm developing a chat app in express by socket.io and this is my code:
well the front end cannot connect to socket io but server is running and i can login
const express = require("express");
const { Server } = require("socket.io");
const helmet = require("helmet");
const cors = require("cors");
const authRouter = require("./routes/authRouter");
const { corsConfig } = require("./controllers/serverController");
const {
Authorization,
AddFriend,
Disconnect,
dm,
} = require("./controllers/socketController");
require("dotenv").config();
const app = express();
const server = require("http").createServer(app);
const io = new Server(server, {
cors: corsConfig,
});
app.use(helmet());
app.use(cors(corsConfig));
app.use(express.json());
//! Routes
app.use("/auth", authRouter);
app.get("/", (req, res) => res.send("Hi"));
io.use(Authorization);
io.on("connection", (socket) => {
console.log("socket")
socket.on("add_friend", (friendName, cb) => {
AddFriend(socket, friendName, cb);
});
socket.on("disconnect", Disconnect);
socket.on("dm", (message) => dm(socket, message));
});
server.listen(5050, () => {
console.log(app.get("env"));
});
but my server isnt running on localhost:5050 this is the error i got :
curl "http://localhost:5050/socket.io/?EIO=4&transport=polling" curl: (7) Failed to connect to localhost port 5050: Connection refused
ive tried to change config of socket server but none of those worked
i have a socketjs file which will create my config and a useEffect hook which inside that ive tried to connect to my server
frontendCode:
socket.js
import { io } from "socket.io-client";
const socket = (user) =>
new io("http://localhost:5050", {
autoConnect: false,
withCredentials: true,
auth: {
token: user.token,
},
});
export default socket;
useSocket.js:
socket.connect();
socket.on("friends", (FriendList) => {
setFriendList(FriendList);
});
socket.on("messages", (messages) => {
setMessages(messages);
});
socket.on("dm", (message) => {
setMessages((prev) => [message, ...prev]);
});
socket.on("connected", (status, username) => {
setFriendList((prev) => {
const friends = [...prev];
return friends.map((friend) => {
if (friend.username === username) {
friend.status = status;
}
return friend;
});
});
});
socket.on("connect_error", () => {
setUser({ loggedIn: false });
});
returned error from frontend:
Firefox can’t establish a connection to the server at ws://localhost:5050/socket.io/?EIO=4&transport=websocket&sid=1uKM4znamAHH8P6kAAKY.

Nodejs How to export Socket IO in controller

In Nodejs how to export socket IO in controller.
Socket.io Version - "socket.io": "^4.5.1",
Socket.js
let io = null;
// module.exports = {
// intialized_connection: (httpServer) => {
// return (io = require('socket.io')(httpServer, {
// cors: {
// origin: '*',
// methods: ['GET', 'POST', 'PUT', 'DELETE'],
// },
// }));
// },
// getIO: () => {
// if (!io) {
// throw new Error('Socket.io is not initialized');
// }
// return io;
// }
// }
class RealTime {
constructor() {
if (io) return io;
io = this;
return io;
}
intialized_connection(httpServer) {
return (io = require('socket.io')(httpServer, {
cors: {
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
},
}));
}
init() {
io.on("connection", function (socket) {
console.log("A user connected", socket.id);
//Whenever someone disconnects this piece of code executed
// socket.on('custom-event', function(data) {
// console.log("Atique data: ", JSON.stringify(data));
// });
// socket.emit('custom-emit', "hello from nodejs")
socket.on('disconnect', function () {
console.log('A user disconnected');
});
});
}
getIO() {
if (!io) {
throw new Error('Socket.io is not initialized');
}
return io;
}
sendEvents(event, data) {
console.log("This.Socket:", this.socket);
return new Promise((resolve, reject) => {
this.getIO().emit(event, data, (response) => {
if (response.error) {
console.error(response.error);
reject(response.error);
} else {
resolve(true);
}
});
});
}
receivedEvents(event) {
console.log("Atique Ahmed Received Events ---->", event);
return new Promise((resolve, reject) => {
this.getIO().on(event, function(err, data) {
console.log("I am emiiting here, ")
if(err) {
reject(err);
}
resolve(data);
});
})
}
}
module.exports = {
RealTime
};
index.js
const express = require('express');
const bodyparser = require('body-parser');
const cors = require('cors');
const fileUpload = require('express-fileupload');
const http = require('http');
// const socketIO = require('./utils/socket');
const { RealTime } = require('./utils/socket');
const socket = new RealTime();
const app = express();
app.use(cors())
app.options('*', cors());
app.use(bodyparser.json({limit: '5mb', extended: true}))
app.use(bodyparser.urlencoded({limit: '5mb', extended: true}))
const authRoutes = require('./routes/authRoutes');
const apiRoutes = require('./routes/routes');
// For File Upload
app.use(fileUpload({
limits: { fileSize: 5 * 1024 * 1024 },
}));
app.use('/auth', authRoutes);
app.use('/user', apiRoutes);
//Capture All 404 errors
app.use(function (req,res,next){
res.status(404).send('Error - Unable to find the requested resource!');
});
app.use((req, res, next) => {
req.socket.on('error', () => {});
next();
});
const server = http.createServer(app);
socket.intialized_connection(server);
socket.init();
app.set('socketio', socket);//here you export my socket.io to a global
module.exports = server;
local.js
require('dotenv').config()
const server = require('./index');
const port = process.env.PORT || 8081;
const chalk = require('chalk');
// Server
server.listen(port, () => {
console.log(chalk.green('╔═══════════════════════════════════════════════════════════'));
console.log(chalk.green('║ Background Server Listening at | port: %s', port));
console.log(chalk.green('╚═══════════════════════════════════════════════════════════'));
});
Routes.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
// Authentication
const authentication = require('../authentication');
// Middleware
const middleware = require('../middleware/headerValidation');
// Permission
const permissions = require('../permission/index')
// Controller
const userController = require('../controllers/userController');
const customerController = require('../controllers/customerController');
app.post('/submit-request', [middleware.bearerTokenPresent, authentication.verifyToken, permissions.fileUploadPermission], (req, res) => {
customerController.submitRequest(req, res);
});
module.exports = app;
customerController.js
exports.submitRequest = async(req, res) => {
const io = req.app.get('socketio');
io.emit('custom-emit', "Hello from nodejs");
io.on('custom-event', function(data) {
console.log("Atique:", JSON.stringify(data))
})
res.json("done")
}
Issue are -
The main issues are - socketio.on an socketio.emit is not working. It is working when I am putting everything, inside init method, I can't do that, I have to write the generic code, so it can be re-usable. -
init() {
io.on("connection", function (socket) {
console.log("A user connected", socket.id);
socket.on('custom-event', function(data) {
console.log("Atique data: ", JSON.stringify(data));
});
socket.emit('custom-emit', "hello from nodejs")
socket.on('disconnect', function () {
console.log('A user disconnected');
});
});
}
Frontend Angular 14, I am using, socket.io-client
Any idea, What I am doing wrong?
The object stored in your globals
app.set('socketio', socket);//here you export my socket.io to a global
is an instance of RealTime class and not of the require('socket.io').Server class.
please cache the reference to the proper object like so:
app.set('socketio',socket.intialized_connection(server));//here you export my socket.io to a global
socket.init();
change customerController.js:
exports.submitRequest = async (req, res) => {
const io = req.app.get('socketio');
///edited from io.on("connection", function (socket) {
io.once("connection", function (socket) {
socket.emit('custom-emit', "Hello from nodejs");
socket.on('custom-event', function (data) {
console.log("Atique:", JSON.stringify(data))
})
res.json("done")
});
}
you however have to keep in mind what listeners you are adding to the io object's "connection" or some other event as No checks are made to see if the listener has already been added. Multiple calls passing the same combination of "connection" and listener will result in the listener being added, and called, multiple times.
Consider using named functions and clearing the listener using removeListener() from time to time.
It is best to keep all your socket event listeners in one file for ease of debugging.
EDIT 1
index.js:
const server = http.createServer(app);
socket.intialized_connection(server);
socket.init();
app.set('socketio', socket);//here you export my socket.io to a global
make the following changes to your socket.js:
let io = null;
/// CHANGE:
let socketID = null;
class RealTime {
constructor() {
if (io) return io;
io = this;
return io;
}
intialized_connection(httpServer) {
return (io = require('socket.io')(httpServer, {
cors: {
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
},
}));
}
init() {
io.on("connection", function (socket) {
console.log("A user connected", socket.id);
/// CHANGE:
socketID = socket.id
//Whenever someone disconnects this piece of code executed
// socket.on('custom-event', function(data) {
// console.log("Atique data: ", JSON.stringify(data));
// });
// socket.emit('custom-emit', "hello from nodejs")
socket.on('disconnect', function () {
console.log('A user disconnected');
});
});
}
/// CHANGE: getIO() {
getSocket() {
if (!io) {
throw new Error('Socket.io is not initialized');
}
return io.sockets.sockets.get(socketID);
}
.
.
.
.
for the receivedEvents and sendEvents to get reference to the socket.
Since you are caching the socket id here, this code will work only for one client properly.
change customerController.js:
exports.submitRequest = async (req, res) => {
const socket = req.app.get('socketio').getSocket();
socket.emit('custom-emit', "Hello from nodejs");
socket.on('custom-event', function (data) {
console.log("Atique:", JSON.stringify(data))
})
res.json("done")
}

Socket connection is not working while using express with next.js

I have a problem with using socket.io in my application.
I use Next.js, Express.js, socket.io, socket.io-client
When I run Next.js server and Express server then access the page, socket is immediately connected. But when I post to /webhook/notify from other server socket.emit("notify", req.body); does not work. But when I reload the backend server, somehow it works for no reason.
Below are my codes
Frontend side
const socket = io.connect("http://127.0.0.1:3000", { cors: true }); //backend server
socket.on("connection", async (data) => { // it works
try {
console.log(data);
} catch (err) {
console.error(err.response);
}
});
socket.on("notify", async (notify) => { // it does not works while I reload backend server
try {
console.log(notify);
} catch (err) {
console.error(err.response);
}
});
Backend side
index.js
const app = express();
const PORT = process.env.PORT || 3000;
app.use(cors({ origin: "http://127.0.0.1:3060" }));
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
const Socket = require("./socket");
const server = app.listen(PORT, function () {
return console.log("Backend server listening on port" + PORT);
});
Socket(server, app);
socket.js
const Socket = require("socket.io");
const axios = require("axios");
module.exports = (server, app) => {
const io = Socket(server, {
cors: {
origin: "*",
},
});
io.on("connection", (socket) => {
console.log("socket is connected");
app.post("/webhook/notify", (req, res, next) => {
try {
socket.emit("notify", req.body);
} catch (err) {
console.error(err.response);
return next(err);
}
});
socket.on("disconnect", () => {
console.log("disconnected");
});
});
};

Trying to reuse socket io instance in a controller but getting an error that socket hasn't been initialized

I'm relatively new to node.js and I'm trying to include socket.io into a controller. The idea is to respond to a client when an order is placed through the response object of express but in addition I'd also like to emit an event so that the restaurant owner sees the orders from all the customers coming in 'live'.
I have an index.js file in an api folder with the following code, where I export api, server and PORT:
`
const express = require('express');
const morgan = require('morgan');
const http = require('http');
const cors = require('cors');
const api = express();
const server = http.createServer(api);
const PORT = process.env.PORT || 3000;
api.use(cors());
api.use(morgan('common'));
api.use(express.urlencoded({ extended: true }));
api.use(express.json({ extended: true }));
api.use('/api/v1', require('../routers'));
api.get('/', (req, res) => {
res.send('Backend running.');
});
module.exports = { api, server, PORT };
In the root of the project I have another index.js file with the following code:
/* eslint-disable no-console */
require('dotenv').config();
const mongoose = require('mongoose');
const { api, server, PORT } = require('./api');
const { MONGO_URI } = require('./config');
mongoose.connect(
MONGO_URI,
{ useNewUrlParser: true, useUnifiedTopology: true },
)
.then(() => console.log('Connected to DB'))
.catch((err) => console.log('Error occured while trying to connect to DB', err));
api.listen(PORT, () => console.log(`Listening on ${PORT}`));
const io = require('./socket').init(server);
io.on('connection', (socket) => {
console.log('Connection success', socket.id);
socket.on('disconnect', () => {
console.log('Connection disconnected', socket.id);
});
});
I've placed the code to initialize socket.io and get an instance of it in a folder named socket with the following code in the index.js file:
/* eslint-disable consistent-return */
/* eslint-disable global-require */
const { Server } = require('socket.io');
let io;
module.exports = {
init: (server) => {
try {
io = new Server(server);
return io;
} catch (err) {
console.log(err);
}
},
get: () => {
if (!io) {
throw new Error('socket is not initialized');
}
return io;
},
};
Then I import the io instance in a controller but when I emit an event I get the error that the socket is not initialized. This is how I import the socket instance and emit an event:
const { OrdersService } = require('../services');
const io = require('../socket/index').get();
module.exports = {
create: async (req, res) => {
const { body } = req;
try {
const order = await OrdersService.create(body);
io.emit('new order', order);
res.status(201).json(order);
} catch (err) {
res.status(400).json(err);
}
},
};
What am I doing wrong? Any help would be greatly appreciated :)
I configured socket.io like I did based on previous questions that were raised on this topic here in stackoverflow.

how to get a response in realtime in Nodejs

Hi I am trying to make a request and receive just the response in realtime using socketIO
and currently I am able to connect to the router but not getting any response as the error shows
Error: io is not defined.
If anyone can please help me to resolve this issue.
Below is the necessary code.
ChatPageProvider.dart
Future<void> addProduct(String message) async {
Map<String, String> headers = {
"Content-Type": "charset=utf-8",
"Content-type": "application/json"
};
const url = 'http://localhost:8080/message/check';
try {
var response = await http.post(url,
headers: headers,
body: json.encode({
"text": message,
}));
socketIO.init();
//Subscribe to an event to listen to
socketIO.subscribe('message', (jsonData) {
//Convert the JSON data received into a Map
Map<String, dynamic> data = json.decode(jsonData);
messages.add(data['message']);
notifyListeners();
});
socketIO.connect();
// final getMessage = Message(
// text: json.decode(response.body)['message'],
// );
print(response.statusCode);
notifyListeners();
} catch (error) {
throw error;
}
}
index.js
const express = require('express');
const app = express();
const notificationdetails = require('../nodePractice/router/notification');
const http = require('http').createServer(app);
const io = require('socket.io')(http);
bodyParser = require('body-parser');
var port = process.env.PORT || 8080;
app.use(bodyParser.json({limit: "50mb"}));
app.use(bodyParser.urlencoded({limit:"50mb",extended:true}));
io.on("connection",(userSocket) => {
console.log('Conntected to port')
io.emit('connected', 80);
})
var server = http.listen(port, ()=> {
console.log('listening on port' + port)
})
app.use(notificationdetails);
notification.js
const express = require('express');
const router = new express.Router()
router.post('/message/check',async(req,res) => {
console.log("Success"); // I am able to get till here but then the error occurs
io.emit("message", req.body)
try {
res.status(201).send();
io.emit("message", req.body)
}catch(e) {
res.status(401);
io.emit("message", req.body)
res.send(e);
}
})
module.exports = router
error
(node:78214) UnhandledPromiseRejectionWarning: ReferenceError: io is not defined
You can create a file like below, give it a name socket-io.js.
var io = require('socket.io')(9999);
module.exports = io;
Then import it first in your index.js like below snippet.
let io = require('./app/utilities/socket-io');
io.on('connection', function (socket) {
...
});
Last, you can import the same file in your notification.js file as well & try below code.
const express = require('express');
const router = new express.Router()
let io = require('./app/utilities/socket-io');
router.post('/message/check',async(req,res) => {
console.log("Success"); // I am able to get till here but then the error occurs
io.emit("message", req.body)
try {
res.status(201).send();
io.emit("message", req.body)
}catch(e) {
res.status(401);
io.emit("message", req.body)
res.send(e);
}
})
module.exports = router

Resources