Express JS mongoDB async await - node.js

Can anyone help me where is the problem view is generated before mongoose get data from database. I already use await but its not waiting for response.
router.get('/', async(req, res, next)=> {
try{
const products = await Product.find({});
res.render('shop/index', { title: 'Express',products });
}catch(e){
console.log(e);
}
});

Imao you tried to do somethins like this:
router.get('/', async(req, res, next)=> {
let products
try{
products = await Product.find({});
}catch(e){
console.log(e);
}
res.render('shop/index', { title: 'Express',products });
});
But as I know the reason to use such syntax is cristmas tree of callbacks.

You can do it like this
router.get('/', async(req, res, next)=> {
try{
Product.find({}).then(products => {
res.render('shop/index', { title: 'Express',products });
});
}catch(e){
console.log(e);
}
});

Related

Cannot fetch data from Nodejs backend to React frontend

I'm building MERN stack CRUD with goolge login
I'm running my server on port:3001
and frontend on port:3000
getAll() {
return axios.get("http://localhost:3001/jobs")
}
try to fetch data with session loggedin
router.get("/", util.isLoggedin, (req, res) => {
Job.find()
// .populate("author")
.limit(20)
.sort({ jobId: -1 })
.then((jobs) => res.json(jobs))
.catch((err) => res.status(400).json("Error:" + err))
})
const util = {}
util.isLoggedin = function (req, res, next) {
console.log(req.isAuthenticated())
if (req.isAuthenticated()) {
next()
} else {
console.log(req.isAuthenticated())
res.redirect("/")
}
}
module.exports = util
I can retrieve the data only on the server side, not frontend.
what can be the solution?
source code:
https://github.com/jamespark89/mern-communitywebsite
it seems like you are not awaiting your promise..
async getAll() {
return await axios.get("http://localhost:3001/jobs")
}
replace
getAll() {
return axios.get("http://localhost:3001/jobs")
}
with
async getAll() {
return await axios.get("http://localhost:3001/jobs")
}
Try to make your get request as an async function I usualy do that:
router.get("/", util.isLoggedin, async (req, res) => {
try {
const res = await Job.find()
// .populate("author")
.limit(20)
.sort({ jobId: -1 })
res.status(400).json({ res })
} catch(err) {
res.status(400).json("Error:" + err)
}
})

passing data to partial express js hbs

currently I am making a notification system with node/express/hbs and mysql. I can insert notification to the database properly , but I can't fetch it my partial file.
here is my code
countNotification: async (req, res) => {
await Notification.count({ where: { status: 'unread' } }).then((notification) => {
if (notification) {
const dashNotification = req.notification;
return dashNotification;
}
});
},
app.use((req, res, next) => {
res.locals.user = req.user;
res.locals.notification = req.dashNotification;
next();
});
i have tried this like that but it is not working , anyone has any solution ?
You should use your middleware above the router:
app.use((req, res, next) => {
res.locals.user = req.user;
res.locals.notification = req.dashNotification;
next();
});
countNotification: async (req, res) => {
await Notification.count({ where: { status: 'unread' } }).then((notification) => {
if (notification) {
const dashNotification = req.notification;
return dashNotification;
}
});
},

Sorting A-Z/Date data from router.get?

Quick question: how can I sort my posts data by date?
router.get('/', async (req, res) => {
try {
const posts = await Post.find()
res.json(posts)
}
catch (err) {
res.json({message: err})
}
})
I came from Django and there you could do something like:
posts = Post.objects.filter().order_by('date')
I'm fairly new to NodeJS and Express. Thanks a lot!
It depends on the what the data structure of the date property is. If they are in JS timestamp format:-
router.get('/', async (req, res) => {
try {
const posts = await Post.find();
const sortedPosts = posts.sort((a,b) => {
return new Date(b.date) - new Date(a.date);
});
res.json(sortedPosts)
}
catch (err) {
res.json({message: err})
}
})
Here I've used the array's sort() method. Learn more

Is there an elegant way to render two sets of mongoose documents?

I have a web page view that requires two sets of mongoose documents, one for "complete tasks" and one for "incomplete tasks."
Here is my current code:
router.get('/', (req, res) => {
Task.find({'completed': false}) // Finding all incomplete tasks
.exec()
.then((incompleteTasks) => {
Task.find({'completed': true}) // Finding all complete tasks
.exec()
.then((completeTasks) => {
res.render('tasks/tasks', {
title: 'Tasks',
incompleteTasks: incompleteTasks,
completeTasks: completeTasks,
});
});
});
});
Is there a way to make this more elegant? Right now, it isn't too bad, but if I had to split up my tasks into more than sets, the code would get pretty messy.
What I thought of was to make the code have the following structure:
let incompleteTasks = /* Get INCOMPLETE tasks */
let completeTasks = /* Get COMPLETE tasks */
res.render('tasks/tasks', {
title: 'Tasks',
incompleteTasks: incompleteTasks,
completeTasks: completeTasks,
});
However, because of the asynchronous nature of mongoose queries, I'm not sure how to do this.
Any suggestions?
Using asynchronous can be helpful.
router.get('/', async (req, res) => {
try{
incompleteTasks = await Task.find({'completed': false}).exec();
completeTasks = await Task.find({'completed': true}).exec()
res.render('tasks/tasks', {
title: 'Tasks',
incompleteTasks: incompleteTasks,
completeTasks: completeTasks,
});
}
catch (e){
//handle your error here
}
});
Since incompleteTasks and completeTasks don't depend on each other, queries should be performed in parallel.
router.get('/', (req, res, next) => {
Promise.all([
Task.find({'completed': false}),
Task.find({'completed': true})
]).then(([incompleteTasks, completeTasks]) => {
res.render('tasks/tasks', {
title: 'Tasks',
incompleteTasks: incompleteTasks,
completeTasks: completeTasks,
});
});
})
.catch(next);
});
It can be written with async..await:
router.get('/', async (req, res, next) => {
try {
const [incompleteTasks, completeTasks] = await Promise.all([
Task.find({'completed': false}),
Task.find({'completed': true})
]);
res.render('tasks/tasks', {
title: 'Tasks',
incompleteTasks: incompleteTasks,
completeTasks: completeTasks,
});
} catch (err) {
next(err);
}
});
Since Express doesn't support promises, all rejections should be handled as a rule of thumb.

ExpressJS Mongoose render view after getting data from database

I need to render view after mongodb provide data from database. I write this code but the main problem is view is generated before getting data.
router.get('/', async(req, res, next)=> {
try{
const products = await Product.find({});
res.render('shop/index', { title: 'Express',products });
}catch(e){
console.log(e);
}
});
You could try doing something like this:
router.get("/", async (req, res, next) => {
Product.find({}, (err, items) => {
if (err) {
console.log(err);
res.status(500).send("An error occurred", err);
} else {
res.render("home", { items });
}
});
});
Actually everything looks great, idk why it's not working. I probably write something like this:
router.get("/", async (req, res) => {
const products = await Product.find({});
if (!products) return res.render("error");
res.render("shop/index", {
title: "Express",
products
});
});

Resources