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
});
});
Related
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
I want to redirect users to "404.ejs" if the post id is entered wrong/mispelled in blogs/:blogId route. How can I accomplish it in below code.
app.get('/blogs/:blogid', (req, res) => {
const requestedId = req.params.blogid;
Blog.findById(requestedId, (err, addedblogpost) => {
if (err) {
console.log(err);
}
else {
res.render("post", {
title: addedblogpost.blogTitle,
content: addedblogpost.blogContent
})
}
})
}
Code for "404"
app.get('*', (req, res) => {
res.render('404');
})
You should make use of express next parameter to get the result you want.
This will call the next "matching" middleware for the current route, assuming this would be your error handler middleware of course.
It should be used as shown below :
app.get('/blogs/:blogid', (req, res, next) => {
const requestedId = req.params.blogid;
Blog.findById(requestedId, (err, addedblogpost) => {
if (err) {
next();
}
else {
res.render("post", {
title: addedblogpost.blogTitle,
content: addedblogpost.blogContent
})
}
})
Express doc : https://expressjs.com/en/guide/using-middleware.html
app.get('/blogs/:blogid', async (req, res) => {
const requestedId = req.params.blogid;
const blog = await Blog.findById(requestedId);
if (!blog) return res.render("404");
res.render("post");
}
to check if the blog is null or not.
I've captured data and display them by doing this:
const items = [];
Task.find({},(err,tasks)=>{
if(err){
console.log(err);
}else{
tasks.forEach((task)=>{
items.push(task.name);
})
}
})
app.get("/", (req, res) => {
today = date.getDate();
res.render('list', { kindOfDay: today, items: items });
})
But when I try to do this instead, it failed to display the data with out any error:
app.get("/", (req, res) => {
const items = [];
Task.find({}, (err, tasks) => {
if (err) {
console.log(err);
} else {
tasks.forEach((task) => {
items.push(task.name);
//console.log(task.name) still works
})
}
});
today = date.getDate();
res.render('list', { kindOfDay: today, items: items });
})
Does anybody knows why the code above refuse to display data when I render the 'list' page?
Thank you!
mongoose find method is asynchronous, res.render might/would execute before the array gets populated. your code should be as below
app.get("/", (req, res) => {
const items = [];
Task.find({}, (err, tasks) => {
if (err) {
console.log(err);
} else {
tasks.forEach((task) => {
items.push(task.name);
//console.log(task.name) still works
});
}
today = date.getDate();
res.render('list', { kindOfDay: today, items: items });
});
})
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);
}
});
I'm trying to reuse my controllers which handle database operations. I'm bit struggling with structuring my application. Here's what I have:
server.js
var apiController = require('./controllers/api');
router.get('/cars', function (req, res) {
// get all cars from DB and render view
apiController.getCars().then(function (cars) {
res.render('index', {cars: cars});
});
});
router.get('/api/cars', function (req, res) {
// get all cars from DB and return JSON
apiController.getCars().then(function (cars) {
res.json(cars);
});
});
controllers/api.js
module.exports = {
getCars: function () {
db.collection('cars').find().toArray( function (err, cars) {
if (err) throw err;
return cars;
});
},
// tried also something like this but this doesn't really work
// for my use case because I don't want to attach any particular
// res to the function
getCars: function (req, res, next) {
db.collection('cars').find().toArray( function (err, cars) {
if (err) throw err;
res.json(cars);
});
},
};
Your current problem is that you expect promises as return in server.js while you use callbacks in the controller. I suggest you change your function getCars to return a Promise. Don't know what ODM/ORM you're using but it might look like something like this:
getCars: function () {
return db.collection('cars').find();
},
server.js
var apiController = require('./controllers/api');
router.get('/cars', function (req, res) {
apiController.get('cars').then(function (cars) {
res.render('index', {cars: cars});
});
});
router.get('/api/cars', function (req, res) {
apiController.get('cars').then(function (cars) {
res.json(cars);
});
});
controllers/api.js
var Promise = require('bluebird');
module.exports = {
get: function (modelName) {
return new Promise(function(resolve,reject){
return db.collection(modelName).find().toArray(function(err, models){
if (err) {
return reject(err);
}
else {
return resolve(models);
}
});
});
}
};
server.js
var apiController = require('./controllers/api');
router.get('/cars', apiController.getCars);
controllers/api.js
function getCarsAsync(req, res, next){
db.collection('cars').find().then(function(carsData){
if(carsData){
return res.send(carsData);
}
else{
return res.status(401).send('User is not authorized');
}
}).catch(function(err){
return next(err);
});
}
module.exports = {
getCars: getCarsAsync
};