How and where initialize socket.io in my express app - node.js

I have an app in the MERN stack and I want to use socket.io for real time notifications. The problem is that I am confused where to initialize socket.io in my app.
I want to send a real time notification on multiple post routes.
Should I just initialize and use socket.io in my very app.js or on every post route needed. I am not sure what to do.
const mongoose = require("mongoose");
const express = require("express");
const app = express();
const socket = require("socket.io");
mongoose
.connect(process.env.MongoDb_Url)
.then(() => {
const io = socket(
app.listen(5000, () => console.log("Server And Database Are Running")),
{
cors: {
origin: "http://localhost:3000",
},
}
);
io.on("connection", (socket) => {
socket.on("message", async (message) => {
const messageCreated = await chatModel.create({ ...message });
socket.emit("createdMessage", messageCreated);
});
});
})
.catch((error) => console.log(error.message));
This is what I am saying. Like how do I use socket.io on every post route to send real time notifications. Please give me the code for it and make it clear for me.

Related

Passing route functions to HTML via Socket.io Websocket

Heyo.
i have an websocket defined like this.
const express = require('express');
const app = express();
const http = require('http');
const { Server } = require('socket.io');
const cors = require('cors');
app.use(cors());
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: "*",
method: ["GET", "POST", "PUT"],
},
});
io.on("connection", (socket) => {
console.log(`user connected: ${socket.id}`);
});
server.listen(3001, () => {
console.log("websocket online");
});
The following code is the function i want to pass to my frontend html via websocket, which is accessed by pressing an button on my frontend html.
app.get("/updateSomething", (req,res) {
//some code
}
My question would be: How do i tell my frontend to access that specific function from my node script via button click.
<button>DoSomething</button>
You can use JavaScript to emit to your socket.io server when you press that button.
For example in your client html:
<button id="doSomethingBtn">DoSomething</button>
<script>
const socket = io();
document.getElementById("doSomethingBtn").addEventListener("click", () => {
socket.emit("buttonClicked", 'someData');
});
</script>
and in your server handle this emit
io.on("connection", (socket) => {
console.log(`user connected: ${socket.id}`);
socket.on("buttonClicked", (someData) => {
console.log("button Clicked!")
// here you can do any code you want including running whatever is in your app.get
});
});
Please dont hesitate to make a comment if you dont understand soemthing or you need more help.

how to use make express endpoints listen to same server as mongoose (apollo server)

i currently have an apollo server interacting with my mongodb database running on a port (localhost or the port given from the host when deployed). i also have another file (app.js) for web scraping that has routes and uses express, running on a different port.
i want the app.js express logic to run on the same port as the call
server.listen({ port: port}) in index.js. how do i do this, please? essentially something like putting the app.get calls in the mongoose.connect which does not seem possible, but so you can get the idea.
moving all the logic in app.js to index.js so the server listens to mongoose, apollo, and all the express endpoints i have in one place on the same, single port.
//index.js
const { ApolloServer } = require('apollo-server');
const mongoose = require('mongoose');
const express = require("express");
const bodyParser = require('body-parser');
const nodemailer = require('nodemailer');
let port = process.env.port || 5000;
const typeDefs = require('./graphql/typeDefs');
const resolvers = require('./graphql/resolvers');
const { MONGODB } = require('./config.js');
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({ req })
});
mongoose.connect(MONGODB, { useNewUrlParser: true })
.then(() => {
console.log("MongoDB connected");
return server.listen({ port: port})
})
.then((res) => {
console.log(`Server running at ${res.url}`);
})
app.js (snippet) used for endpoints that return web scraping data
const express = require("express");
const cors = require('cors')
const cheerio = require('cheerio');
const axios = require('axios');
const app = express();
const port = 5001;
app.get("/events/", function(req, res) {
// redacted logic
let { zipCode } = req.query;
// Create a new yelpAPI object with your API key
let apiKey =[redacted];
let yelp = new yelpAPI(apiKey);
// Set any parameters, if applicable (see API documentation for allowed params)
let params = [{ location: zipCode }];
// Call the endpoint
yelp.query('events', params)
.then(data => {
// Success
res.send(data);
})
.catch(err => {
// Failure
console.log(err);
});
});
app.listen(port, () => console.log(`CORS-enabled web server listening on port ${port}!`));

Translating server code to ES6 using socket.io

We are complete newbies to socket.io and express. And we have followed along this tutorial to learn socket.io https://www.valentinog.com/blog/socket-react/
And now we want to translate this line of code (older style):
const index = require("./routes/index").default
to ES6, below:
import router from './routes/index'
app.use('/', router)
But it does not work for us. We get this error in the terminal.
Full server.js code here
import express from 'express'
const app = express()
import { createServer } from 'http'
const server = createServer(app)
import { Server } from "socket.io"
const io = new Server(server)
import cors from 'cors'
import router from './routes/index'
const port = process.env.PORT || 4001
app.use('/', router)
app.use(index)
app.use(cors())
app.use(express.json())
let interval
io.on("connection", (socket) => {
console.log("New client connected")
if (interval) {
clearInterval(interval)
}
interval = setInterval(() => getApiAndEmit(socket), 1000)
socket.on("disconnect", () => {
console.log("Client disconnected")
clearInterval(interval)
})
})
const getApiAndEmit = socket => {
const response = new Date()
socket.emit("FromAPI", response)
}
app.listen(port, () => {
// eslint-disable-next-line
console.log(`Server running on http://localhost:${port}`)
})
I was able to use socket.io on my project like so:
const app = express()
const http = require('http').createServer(app)
const socketIo = require('socket.io')(http)
In other words I used require and did not use router. This might work for you unless there is a specific reason you need to do otherwise.

How to separate Socket.IO events from server.js?

I created Express, Node, React app.
Now, i want to integrate socket.io to the app.
I searched all over the internet and i found that all the socket.io events are in the initial server.js/app.js file.
But, i want to separate the socket.io events from the main file and then import it to the main file, just like routes/controllers files.
My code right now:
var app = require("express")();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
const mongoose = require("mongoose");
const stocks = require("./routes/stockRoutes");
const bodyParser = require("body-parser");
const cors = require("cors");
const port = 5000;
app.use(stocks);
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.set("socketio", io);
const uri =
"mongodb+srv://admin:admin1234#investockcluster0.jp2wh.mongodb.net/<stocks_data>?retryWrites=true&w=majority";
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
});
const connection = mongoose.connection;
connection.once("open", () => {
console.log("MongoDB database connection established successfully");
});
io.on("connection", (socket) => {
socket.emit("hello", "world");
console.log("New Connection");
});
http.listen(port, () => {
console.log(`Server is running on port: ${port}`);
});
I want that this code will be in file like "socketEvents.js" and then require it.
io.on("connection", (socket) => {
socket.emit("hello", "world");
console.log("New Connection");
});
Thanks a lot :)
Just put your socket.io code in another module and pass in the server in an initialization method:
// in sock.js
module.exports = function(server) {
const io = require("socket.io")(server);
io.on("connection", (socket) => {
socket.emit("hello", "world");
console.log("New Connection");
});
// put other things that use io here
}
Then, in your main file:
require('./sock.js')(http);
FYI, http is a crummy variable name for your server. You really ought to name it server.

WebSocket connection to 'ws://localhost:5000/socket.io/...' failed: Error during WebSocket handshake: Unexpected response code: 400

I am trying to create a chat app which, uses a real-time database with MongoDB and Websocket.
This is my first React, MongoDB, and Websocket Project, so please excuse possible trivialities. :D
I am currently working on creating a new user, refreshing the database, and finally displaying the created user in every user's frontend in real-time.
Creating and saving a new user works fine and also logging the new user's data in real-time after the database changed (via socket.io) is working as well. Now, I would like to access the information that the database changed in the frontend of my app, so I can refresh the unordered list of users. Now there is the problem I'd like to solve: I try to connect the frontend with my backend by using this code:
//...
import socketIOClient from "socket.io-client";
const ENDPOINT = "localhost:5000";
const MainContentArea = () => {
useEffect(()=>{
const socket = socketIOClient(ENDPOINT);
socket.on("changes", data => {
console.log(data);
})
});
//...
The following is my backend code:
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const index = require('./routes/index');
const port = process.env.PORT || 5000;
const app = express();
app.use(index);
const server = app.listen(port, () => {
console.log(`Server ist running on port: ${port}`);
})
const io = socketIo(server).listen(server);
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config({
path: './.env'
});
const Users = require('./models/user.model');
app.use(cors());
app.use(express.json());
const usersRouter = require('./routes/users');
app.use('/users', usersRouter);
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
},
function(err){
if(err){
console.log("server.js err line 44");
throw err;
}
io.on('connection', (socket) => {
console.log('user connected');
socket.on('disconnect', (socket) => {
console.log('user disconnected');
})
})
Users.watch().on('change', (change) => {
console.log('socket says: something changed in db');
console.log('change: ', change.fullDocument);
io.to(change.fullDocument).emit('changes',change.fullDocument)
})
}
);
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDB database connection established successfully");
})
I keep getting the Error message:
WebSocket connection to 'ws://localhost:5000/socket.io/? EIO=3&transport=websocket&sid=33wU6D8PnqclT3iZAAAB' failed: Error during WebSocket handshake: Unexpected response code: 400
I am using Chrome and I am working on MacOS.
I am very thankful for any suggestions that might help solve my problem.
I hope, how I posted my question is helpful for anybody who is willing to help me with this. If not, feel free to give me suggestions on what to do better next time! This is my first post here.

Resources