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.
Related
If I am using this function I am getting proper response.
router.get('/', function(req, res, next) {
var products = Product.find();
res.render('shop/index', { title: 'Shopping-Cart', products: products });
});
If I am using below function my local server is not giving any response and keep loading.
router.get('/', function(req, res, next) {
Product.find(function (err, docs){
res.render('shop/index', { title: 'Shopping-Cart', products: docs });
});
});
Help me to solve this problem.
Try this. Add match object to find method.
router.get('/', function(req, res, next) {
Product.find({}, function (err, docs){
res.render('shop/index', { title: 'Shopping-Cart', products: docs });
});
});
The second one is simply wrong. This whole thing :
function (err, docs){
res.render('shop/index', { title: 'Shopping-Cart', products: docs });
}
is being passed to the find() method as a parameter.It makes absolutely no sense
Correct would be this:
Product.find().then(docs=>{
res.render('shop/index', { title: 'Shopping-Cart', products: docs })
}).catch(err=>console.log(err))
Since you haven't specified the database you are using, I'll assume something similar to MongoDB. The first parameter to the find operation must be a query object if any.
Documentation
So, you can tweak your code in any of the ways like this:
var products = await Product.find(); // Using async-await
res.render('shop/index', { title: 'Shopping-Cart', products: products });
Product.find({}, function(err, products) { // Using callbacks
res.render('shop/index', { title: 'Shopping-Card', products: products });
}
Product.find().then(function(products) { // Using Promises
res.render('shop/index', { title: 'Shopping-Card', products: products });
}
I'm not sure what I'm doing wrong here? The GET works fine with the same info, but the DELETE keeps giving me a 500 Internal server error, and my server logs say, "StoredProduct.delete is not a function"
For the sake of this post, I'm including the GET route and GET JS below, just to show those are working, so I think my routes are set up correctly?
These are my routes
router.get('/:productID', (req, res, next) => {
StoredProduct
.findOne({
_id: req.params.productID
})
.then(product => {
res.status(201).json(product);
});
});
router.delete('/:productID', (req, res) => {
StoredProduct
.delete(req.params.productID);
res.status(204).end()
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
And this is my JS
$.ajax({
type: 'GET',
url: '/products/' + productID,
success: function(product) {
$editProdName.append(`${product.name}`);
$addPrice1.val(product.prices[0].price);
$addPrice2.val(product.prices[1].price);
$addPrice3.val(product.prices[2].price);
$selectedUnit.val(product.size);
}
});
$('#deleteme').on('click', function(e) {
e.preventDefault();
console.log(productID);
$.ajax({
type: 'DELETE',
url: '/products/' + productID,
success: function(){
console.log('yippee');
}
});
});
You can use mongoose.deleteOne() and search by id and delete:
router.delete('/:productID', (req, res) => {
StoredProduct
.deleteOne({ _id: req.params.productID}).then(data =>
res.status(204).end()).catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
});
Do you use mongoose?
If so try to
StoredProduct.deleteOne({ id: req.params.productID }, function (err) {});
Also from http://api.jquery.com/jquery.ajax/:
Deprecation Notice: The jqXHR.success(), jqXHR.error(), and jqXHR.complete() callbacks are removed as of jQuery 3.0. You can use jqXHR.done(), jqXHR.fail(), and jqXHR.always() instead.
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 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
});
});
I'm working with Express, Hoganjs, Nodejs.
The code below keeps returning "500 TypeError: Cannot call method 'json' of undefined"
I figure there is something wrong with how I am calling getUsers, but I'm too much of a newbie to figure it out. None of the tutorials or forums I have referred to are helping as of yet.
exports.admin = function(req, res){
getUsers(function(error, res){
res.render('admin', {
title: 'Admin',
userlist: res
});
});
};
function getUsers(req, res) {
res.json([
{username: "fake", permission: "admin" },
{username: "fake2", permission: "user" }
])
}
exports.getUsers = getUsers;
OK, so your code snippet is not properly formatted and thus hard to read, but I think exports.admin is being called as an express route that takes req, res. So far so good. Then you call getUsers and pass it a callback, but getUsers doesn't take a callback, it takes req, res as well. It's unclear what you're trying to do, but something like this would be reasonable:
exports.admin = function(req, res) {
loadUsers(function (error, users) {
if (error) {
return res.status(500).send(error);
}
res.render('admin', {
title: 'Admin',
userlist: users
});
}
};
exports.getUsers = function(req, res) {
loadUsers(function (error, users) {
if (error) {
return res.status(500).send(error);
}
res.send(users);
});
}
function loadUsers(callback) {
process.nextTick(function () {
callback(null, [
{username: "fake", permission: "admin" },
{username: "fake2", permission: "user" }]
);
});
}
An even better pattern would be to code loadUsers as middleware, FYI.