I want to write a real-time chat application with socket.io and because my server and app file are separate, I kind of have no clue that how should I structure it to use socket.io instance in other parts of my app.
This is my app.js file.
const express = require("express");
const pug = require("pug");
const app = express();
module.exports = app;
and this is my server.js file
const app = require("./app");
const mongoose = require("mongoose");
mongoose
.connect(`mongodb://localhost:27017/${process.env.DATABASE}`)
.then(() => {
app.listen(process.env.PORT);
})
.catch((err) => {
console.error(`connection failed: ${err}`);
});
what is the best way to create an instance of socket.io and start it's connection for use in other parts of app?
You can use http with express app and then connect sockets through that http connection and you can listen and emit the topics inside the io.on('connection')
const app = require("./app");
const mongoose = require("mongoose");
const http = require('http').Server(app);
const io = require('socket.io')(http);
mongoose
.connect(`mongodb://localhost:27017/${process.env.DATABASE}`)
.then(() => {
app.listen(process.env.PORT);
io.on('connection', socket => {
console.log('socket connected',socket);
});
})
.catch((err) => {
console.error(`connection failed: ${err}`);
});
I will prefer this second way:
App.js
const express = require("express");
const pug = require("pug");
const app = express();
module.exports = app;
Server.js
const app = require("./app");
const realtime = require("./realtime");
const mongoose = require("mongoose");
const server = require("http").Server(app);
mongoose
.connect(`mongodb://localhost:27017/${process.env.DATABASE}`)
.then(() => {
app.listen(process.env.PORT);
require("./realtime.js")(server);
})
.catch((err) => {
console.error(`connection failed: ${err}`);
});
Realtime.js
module.exports = (app) => {
const io = require("socket.io")(app);
io.on("connection", (socket) => {
console.log("Socket connected")
})
};
Related
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}!`));
This is what I am using. io.on() was working fine but after using mongoose.connect(), it's not working anymore. In terminal only showing
server is running:5000 mongo db connection null
Not sure why io.on() is not working.
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const http = require('http').createServer(app);
const io = require('socket.io')(http);
const mongoose = require('mongoose');
const dbUrl = '' //removed db url for security reason.
app.use(express.static(__dirname));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({"extended":false}));
let message = []
app.get('/messages',(req,res)=>{
res.send(message)
})
app.post('/messages',(req,res)=>{
message.push(req.body)
io.emit('message',req.body)
res.sendStatus(200);
})
mongoose.connect(dbUrl, { useNewUrlParser: true }, (err) => {
console.log('mongo db connection', err)
})
io.on('connect',(socket)=>{
console.log("user connected")
})
const server = http.listen(5000,(err)=>{
if(err){
console.error();
}
console.log("server is running:"+ server.address().port);
});
this is my index.js file it's work for me
I'm new in node and mongo.
I'm trying to connect mongo db with my node server but this error appears.
Error:getaddrinfo ENOTFOUND locahost
[nodemon] app crashed - waiting for file changes before starting...
server.js
`const express = require('express');
require('colors');
const products = require('./data/products');
const dotenv = require('dotenv');
//dotenv config
dotenv.config();
const { connectDb } = require('./config/config')
connectDb();
const app = express();
app.get('/', (req, res) => {
res.send('<h1>Welcome to Node server</h1>')
})
app.get('/products', (req, res) => {
res.json(products);
})
app.get('/products/:id', (req, res) => {
const product = products.find(p => p.id === req.params.id);
res.json(product);
})
const PORT = 8080;
app.listen(process.env.PORT || PORT, () => {
console.log(`Server running in ${process.env.NODE_ENV} mode on port ${process.env.PORT}`.inverse.green)
})`
config.js
const mongoose = require('mongoose');
require('colors');
const connectDb = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI, {
})
console.log(`MongoDB connected ${conn.connection.host}`.yellow)
} catch (error) {
console.error(`Error:${error.message}`.inverse.red);
process.exit(1);
}
};
module.exports = { connectDb }
.env
PORT = 8080
NODE_ENV = development
MONGO_URI = mongodb://locahost:27017/local
Hi in my express project, I have my index file where I require different files to startup my application. These require a database connection file, a file for logging stuff using winston and a file for configuring routes.
I use the require() statement within express to call these files, and when I run the application(using nodemon), I expect some messages to be logged to the terminal verifying that the files have been called, however no messages occur.
Here is my code:
index.js:
const express = require('express')
const app = express()
require('./startup/logging') ()
require('./startup/db') ()
require('./startup/routes') (app)
const port = process.env.PORT || 3000
app.listen(port, () => winston.info(`Listening on port: ${port}`))
db.js:
const mongoose = require('mongoose')
const winston = require('winston')
module.exports = function() {
mongoose.connect('mongodb://localhost/dwg', {useNewUrlParser: true, useUnifiedTopology: true})
.then(() => winston.info('Connected to MongoDB...'))
.catch(err => console.error("Error"))
}
logging.js:
const winston = require('winston');
module.exports = function() {
winston.handleExceptions(
new winston.transports.File({ filename: 'uncaughtExceptions.log' }));
process.on('unhandledRejection', (ex) => {
throw ex;
});
winston.add(winston.transports.File, { filename: 'logfile.log' });
}
routes.js:
const express = require('express');
module.exports = function(app) {
app.use(express.json())
}
No database is created when running the application. I can confirm this by looking at mongodb compass. The message that is meant to be printed by app.listen() is also not printed to the console. Does anybody know the issue? Thank you.
The problem doing it this way is your app starts before it gets a chance to do rest of work like creating db connection etc. You should start the app only when these tasks are done. something like this
const express = require('express')
const app = express()
const logging = require('./startup/logging');
const db = require('./startup/db');
const routes = require('./startup/routes');
const port = process.env.PORT || 3000
app.listen(port, async () => {
await logging();
await db();
await routes();
// assuming you have winston here.
winston.info(`Listening on port: ${port}`)
})
Mongo part is defintely async so need await. Check if routes and logging needs await or not.
I'm pretty new to sockets and I've been struggling to implement some of the documentation i've seen online. This is my set up currently and I wanted to run socket.io against just the healthcheck api endpoint (/api/v1/healthcheck) how would I go about running socket io in the healthcheck controller? and emit changes to the response? Any help is appreciated, i'm tearing my hair out :(
Server.js
const socket = require('socket.io')
const healthcheck = require('./routes/healthcheck');
const auth = require('./routes/auth');
const users = require('./routes/users');
const server = app.listen(
PORT,
console.log(
`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.cyan.bold
)
);
let io = require('socket.io')(server);
app.set("io", io);
//Auth
app.use('/api/v1/auth', auth);
app.use('/api/v1/users', users);
//Health check
app.use('/api/v1/healthcheck', healthcheck);
/routes/healthcheck.js
const express = require('express');
const { checkHealth } = require('../controllers/healthcheck');
const router = express.Router();
router.post('/', checkHealth);
module.exports = router;
/controllers/healthcheck.js
const asyncHandler = require('../middleware/async');
exports.checkHealth = asyncHandler(async (req, res, next) => {
res.status(200).json({
success: true,
data: {
status: "Alive!"
}
});
});
You can pass in the instance of io into that healthcheck route and then simply listen to events and take action. Sample code below.
server.js
const socket = require('socket.io')
const server = app.listen(
PORT,
console.log(
`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.cyan.bold
)
);
let io = require('socket.io')(server);
app.set("io", io);
// pass in io to the relevant route
const healthcheck = require('./routes/healthcheck')(io);
const auth = require('./routes/auth');
const users = require('./routes/users');
//Auth
app.use('/api/v1/auth', auth);
app.use('/api/v1/users', users);
//Health check
app.use('/api/v1/healthcheck', healthcheck);
healthcheck route
const express = require('express');
const { checkHealth } = require('../controllers/healthcheck');
const router = express.Router();
module.exports = (io) => {
router.post('/', checkHealth);
io.on('connection', socket => {
socket.emit('hello', {message: 'helloworld'});
socket.on('reply', checkHealth.someMethod);
});
return router;
}
I would rather create endpoints in files - same as you do for express routes, and init these in your server.js as follows:
let io = require('socket.io')(server);
app.set("io", io);
io.on('connection', socket => {
require('./myendpointexample')(socket);
});
myendpointexample.js
module.exports = (socket) => {
socket.on('myevent', (message) => {
mycontroller.myFunction(message).then(result => {
socket.emit('myEvent', result);
});
});
};