I need to display Invitation and Comments in the same rendered file (show.hbs)
I have this code here, and it's working fine, except I cannot achieve that comment's would also display. I would really appreciate any help.
I'm not getting any errors with this code.
app.get('/invitation/:id', (req, res) => {
let id = req.params.id;
if(!ObjectID.isValid(id)){
return res.status(404).send();
}
Comment.find({inviteId: id}).then((comment) => {
if(!comment){
return res.status(404).send();
}
res.render('show.hbs', {comment});
}, (e) => {
res.status(404).send();
});
Invitation.findById(id).then((invitation) => {
if(!invitation){
return res.status(404).send();
}
res.render('show.hbs', {invitation});
}, (e) => {
res.status(404).send();
});
}, (e) => {
console.log('Unable to find invitation', e);
});
You can do something like this,
Invitation.findById(id).then((invitation) => {
if (!invitation) {
return res.status(404).send();
}
Comment.find({ inviteId: id }).then((comment) => {
if (!comment) {
return res.status(404).send();
}
res.render('show.hbs', { comment, invitation});
}, (e) => {
res.status(404).send();
});
}, (e) => {
res.status(404).send();
});
and render it with both invitation and comment
Tnx to #vibhor1997a but this is much prettier
try {
let invitation = await Invitation.findById(id).then((invitation) => {
if (!invitation) {
return res.status(404).send();
}
let comments = await Comment.find({ inviteId: id })
if (!comments) {
return res.status(404).send();
}
return res.render('show.hbs', { comments, invitation});
} catch (e) {
return res.status(500).send();
}
You didn't paste your error message, but I'm pretty sure it's something like Error: Can't set headers after they are sent to the client.
Just nest your queries or use await https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await.
Related
i have this code:
function isAdmin(idOfChat, IdOfUser, ctx) {
//function
return isAdminBoolean
}
bot.command("test", ctx => {
if (isAdmin(ctx.message.chat.id, ctx.message.from.id) == true) {
ctx.reply("Admin")
}else{
ctx.reply("._.")
}
})
how to make it work?
sorry for my bad English)))
You should re-write your method as a promise (because Telegraf queries from Telegram API, so, your isAdmin method could be like this)
function isAdmin(idOfChat, IdOfUser, ctx) {
return new Promise((resolve, reject) => {
//Get user information first
ctx.telegram.getChatMember(idOfChat, IdOfUser).then((user) => {
//Then check if user is admin (or creator)
resolve(user.status == "administrator" || user.status == "creator");
})
.catch((error) => {
//Reject if it's an error
reject(error);
});
});
}
Then, for use it into your main function, you should have to handle it like this:
bot.command("test", ctx => {
isAdmin(ctx.message.chat.id, ctx.message.from.id, ctx).then((result) => {
if (result) {
ctx.reply("Admin");
} else {
ctx.reply("._.");
}
})
.catch((error) => {
ctx.reply("An error has ocurred trying to get user rank: " + JSON.stringify(error));
});
});
I'm trying to learn how to implement transactions for a simple app in Mongoose with express for a RESTful API.
I've managed to put together a small one change function using the mongoDB session.withTransaction() helper function.
This code block runs with no errors and the document appears in the DB as I would expect.
function createCourse() {
try {
return Course.createCollection()
.then(() => mongoose.startSession())
.then(session => {
session.withTransaction(() => {
return Course.create(
[
{
author: "Larry",
category: "web",
tags: ["tag1", "tag2"],
isPublished: false,
price: 15,
name: "Tester series 3"
}
],
{ session }
);
});
});
} catch (error) {
console.error(error);
}
}
I feel like I'm missing something with how to structure my operations with this function.
Putting everything together into an Express POST method, looks like this works but I'd appreciate a code-review of it.
Also, how can I go about testing that the code is correctly handling errors/roll-backs? Put session.abortTransaction(); somewhere within the sesson.withTransaction() block?
router.post("/", async (req, res) => {
try {
validateRental(req.body);
} catch (error) {
return res.status(400).send(error.details[0].message);
}
let customer = null;
try {
customer = await Customers.findById(req.body.customerId);
} catch (err) {
return res.status(400).send("Invalid customer.");
}
let movie = null;
try {
movie = await Movies.findById(req.body.movieId);
} catch (err) {
return res.status(400).send("Invalid movie.");
}
if (movie.numberInStock === 0)
return res.status(400).send("Movie not in stock.");
try {
mongoose.startSession().then(session => {
session.withTransaction(async () => {
let rental = new Rentals({
renter: {
_id: customer._id,
name: customer.name,
phone: customer.phone,
isGold: customer.isGold
},
movie: {
_id: movie._id,
title: movie.title,
dailyRentalRate: movie.dailyRentalRate
}
});
await rental.save({ session });
movie.numberInStock--;
await movie.save({ session });
res.send(rental);
});
});
} catch (err) {
res.status(500).send(err.message);
}
});
I am trying to replace a string in url . Here is image of it
in this image I want to replace lssplalpha with lssplprod which are in pics array. For that I created an api . Here is a code
apiRoutes.get('/SchoolListing_lssplalpha_Replace',function(req, res) { schoolListModel.find({},function(err,check){
if(err){
return console.log(err);
}
else{
for(var i=0;i<check.length;){
var f=0;
for(var j=0;j<check[i].pics.length;j++){
f++;
var newTitle = check[i].pics[j].replace("lssplalpha","lsslprod");
check[i].pics[j] = newTitle;
console.log("after change",check[i].pics[j]);
check[i].save(function (err) {
if(err) {
console.error('ERROR!');
}
});
}
if(j==check[i].pics.length&&j==f){
i++;
}
}
console.log("i value",i);
console.log("check length",check.length);
if(i==check.length){
return res.json({status:true,message:"Updated Schools"}); }
}
});
});
I am getting success response . When I go and check database nothing changed in db. To know the reason I write log of it. When I see logs it was replacing correctly. But I didn't understand why those are not reflecting in database? Here is an image of log in console
Please help me to come out of this
The issue here is you are running a for loop (synchronous) where you are calling the model.save() operation which is asynchronous and the loop keeps iterating but the results of the async calls come later. The process of saving a database item in an array takes some time and Node.js knows this, so it starts the update and then just moves on trying to update the next item in the array. Once the write operation is complete a callback function is run, but by that point the loop has completed and there is no way to know which items finish in what order.
You could use the Bulk Write API to update your models. This allows you to sends multiple write operations to the MongoDB server in one command. This is faster than sending multiple independent operations (like) if you use create()) because with bulkWrite() there is only one round trip to MongoDB.
The following examples show how you can use the bulkWrite.
Using async/await:
apiRoutes.get('/SchoolListing_lssplalpha_Replace', async (req, res) => {
try {
let ops = [];
const docs = await schoolListModel.find({}).lean().exec();
docs.forEach(doc => {
const pics = doc.pics.map(pic => pic.replace("lssplalpha", "lsslprod"));
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": { pics }
}
}
});
});
const result = await schoolListModel.bulkWrite(ops);
console.log('Bulk update complete.', result);
res.status(200).json({
status: true,
message: "Updated Schools"
});
} catch (err) {
res.status(400).send({
status: false,
message: err
});
}
});
Using Promise API:
const bulkUpdate = (Model, query) => (
new Promise((resolve, reject) => {
let ops = [];
Model.find(query).lean().exec((err, docs) => {
if (err) return reject(err);
docs.forEach(doc => {
const pics = doc.pics.map(pic => (
pic.replace("lssplalpha", "lsslprod")
));
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": { pics }
}
}
});
if (ops.length === 500) {
Model.bulkWrite(ops).then((err, result) => {
if (err) return reject(err);
ops = [];
resolve(result);
});
}
});
if (ops.length > 0) {
Model.bulkWrite(ops).then((err, result) => {
if (err) return reject(err);
resolve(result);
});
}
});
})
);
apiRoutes.get('/SchoolListing_lssplalpha_Replace', (req, res) => {
bulkUpdate(schoolListModel, {}).then(result => {
console.log('Bulk update complete.', result);
res.status(200).json({
status: true,
message: "Updated Schools"
});
}).catch(err => {
res.status(400).send({
status: false,
message: err
});
});
});
You are running asynchronous call model.save() in for loop(synchronous)
To make your for loop synchronous you can use for...of loop which works asynchronous, also you will not need to add multiple checks like you have done in your code.
Try following code, it will work
apiRoutes.get('/SchoolListing_lssplalpha_Replace', function (req, res) {
schoolListModel.find({},function (err, check) {
if (err) {
return console.log(err);
}
else {
for (let checkObj of check) {
let newPicArr=[];
for (let pic of checkObj.pics) {
pic = pic.replace("lssplalpha", "lsslprod");
newPicArr.push(pic);
}
checkObj.pics=newPicArr;
checkObj.save(function (err) {
if (err) {
console.error('ERROR!');
}
});
}
return res.json({ status: true, message: "Updated Schools" });
}
});
});
I Don't want to make checks as if (!isPresent) then do this ....
Is their any way to bypass all the then when my work is complete
var isPresent=false;
myPromise
.then((employee) => {
if (employee) {
// throw 'employee already exist';
isPresent = true;
return res.data(mapper.toFullModel(employee));
}
return model;
});
.then(model => {
if (!isPresent) {
return new db.employee(model).save();
}
})
.then(employee => {
if (!isPresent) {
employee.token = auth.getToken(employee);
return employee.save();
}
})
.then(employee => {
if (!isPresent) {
res.data(mapper.toFullModel(employee));
}
})
.catch(err => {
res.failure(err);
});
You can rewrite your promise chain so the second part of it gets nested:
myPromise.then(employee => {
if (employee) {
return res.data(mapper.toFullModel(employee));
}
return new db.employee(model).save().then(employee => {
employee.token = auth.getToken(employee);
return employee.save();
}).then(employee => {
return res.data(mapper.toFullModel(employee));
});
}).catch(err => {
res.failure(err);
});
I have tried everything and can't figure out what i am doing wrong. I have no problem posting data from the client to the server but the other way around i can't get it to work.
The only response i get in my client is ReadableByteStream {}.
This is my code on the client:
export function getAllQuestionnairesAction(){
return (dispatch, getState) => {
dispatch(getAllQuestionnairesRequest());
return fetch(API_ENDPOINT_QUESTIONNAIRE)
.then(res => {
if (res.ok) {
console.log(res.body)
return dispatch(getAllQuestionnairesSuccess(res.body));
} else {
throw new Error("Oops! Something went wrong");
}
})
.catch(ex => {
return dispatch(getAllQuestionnairesFailure());
});
};
}
This is my code on the server:
exports.all = function(req, res) {
var allQuestionnaires = [];
Questionnaire.find({}).exec(function(err, questionnaires) {
if(!err) {
console.log(questionnaires)
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ a: 1 }));
//res.json(questionnaires)
}else {
console.log('Error in first query');
res.status(400).send(err);
}
});
}
I'm doing some guesswork here, since I'm not sure what flavor of fetch you are currently using, but I'll take a stab at it based on the standard implementation of fetch.
The response inside the resolution of fetch typically does not have a directly readable .body. See here for some straight forward examples.
Try this:
export function getAllQuestionnairesAction(){
return (dispatch, getState) => {
dispatch(getAllQuestionnairesRequest());
return fetch(API_ENDPOINT_QUESTIONNAIRE)
.then(res => {
if (res.ok) {
return res.json();
} else {
throw new Error("Oops! Something went wrong");
}
})
.then(json => {
console.log(json); // response body here
return dispatch(getAllQuestionnairesSuccess(json));
})
.catch(ex => {
return dispatch(getAllQuestionnairesFailure());
});
};
}