Can't use a variable from an await mongodb query - javascript

I'm having a problem using the mongodb query result on another query.
I hope this code explains it (it's written inside an async function) - Please notice that i'm using created_comment._id in the second query:
let created_comment = await Comment.create(new_comment, (err, newReturnedComment)=>{
if(err){
console.log(err);
}
});
await User.findOneAndUpdate({_id: req.user._id},{ $addToSet: {commentsIds: created_comment._id} },
function(err, updated_user) {
if (err) {
console.log(err);
}
});
so even though i'm using await in the first query, when i try to access the created_comment variable i'm not getting anything. is it because create and findOneAndUpdate are not promises? Can you please refer me to a guide that explains whats the best way to make such queries on a nodejs backend?
Thank you.

Do not pass a callback to mongodb functions if you want to use async/await and expect the calls to return promises. Just write
try {
const created_comment = await Comment.create(new_comment);
const updated_user = await User.findOneAndUpdate({_id: req.user._id}, {$addToSet: {commentsIds: created_comment._id}});
} catch(err) {
console.log(err);
}

Related

Trying to delete a doc Mongoose using findByIdAndDelete but im always getting back a null

Trying to delete a doc Mongoose using findByIdAndDelete but im always getting back a null when I know the doc id am passing to the function exists in MongoDB
I've tried:
findByIdAndRemove
findByIdAndDelete
findOneAndDelete -> this with the code below deletes two docs rather than one!
async function deleteCourse(id)
{
const result = await Course.findByIdAndDelete(id,(err, res) => {
if (err){
console.log(err)
}
else{
console.log("Deleted course: ", res);
}
})
}
deleteCourse('5a68fdf95db93f6477053ddd')
As #Yousaf suggested, you dont need the callback function if you are using async/await function. Also use try/catch to have the same behavior.
async function deleteCourse(id)
{
try {
const result = await Course.findByIdAndDelete(id);
console.log("Deleted course: ", result);
} catch(err) {
console.log(err)
}
}
deleteCourse('5a68fdf95db93f6477053ddd')

Improve callback code into async await mongoose

I want improve my old callbacks code in mongose with async/await methods (which are much better to read and organized)
PUT is the problem
I a have a findById, which are correctly
The problem is when try to update document with await user.save(userWithNewProps)
// put
app.put('/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id).exec()
if (user === null) return res.status(404).json(null)
const userWithNewProps = {name: 'Homer', lastame: 'Simpson'}
const userUpdated = await user.save(userWithNewProps) // Doesn't works!
res.status(200).json(userUpdated)
} catch (e) {
return res.status(500).json(e)
}
})
I tried to study many tutorials, and other questions, but is some difficult for me.
Can you check my error?
callback hell
This is the original callback code, works fine, but is the callback hell and demonic spirits:
// put
app.put(
'/:id',
(req, res) => {
User.findById(req.params.id, (err, userFound) => {
if (err) {
return res.status(500).json(err);
}
if (!userFound) {
return res.status(404).json(err);
}
userFound.name = 'Homer';
userFound.lastname = 'Simpson';
userFound.save((err, userUpdated) => {
if (err) {
return res.status(500).json(err);
}
res.status(200).json(userUpdated);
});
});
});
Many thanks
As I understand from our discussion in comments, the problem is in the updating and not when saving data, so you need to inform Mongoose's change tracking of the change.
Informing Mongoose about the changes can be handled by using the markModified() method and it should be before saving.
user.name = 'Homer';
user.lastname = 'Simpson';
user.markModified('name');
user.markModified('lastname');
await user.save();
Regards :)

How can i extract values from promise and send them to client via node.js server?

I have a promise that returns data and I want to pass values of the promise as a response to client(web browser). I know i should probably use asynchronous js, but I'm not sure how to do that. Could you please give me some advice?
Here is how it looks like:
if(req.url === "/api/posts"){
res.writeHead(200, {"Content-Type": "application/json"})
let db = new AppDAO('./db/db.sqlite3')
const postsDb = new PostsRepository(db)
let posts = postsDb.getAll()
db.close()
console.log(posts)
res.end()
}
What you need is to build the response when the DB Promise resolves
postsDb.getAll().then(posts => {
console.log(posts)
res.send(posts)
}).finally(() => db.close())
Or if you want to use the modern syntax, and can declare the surrounding function as async:
try {
const posts = await postsDb.getAll()
console.log(posts)
res.send(posts)
} catch(e) {
// Handle database error
} finally {
db.close()
}

How to put AWS DynamoDB docClient.get item into variable?

I'm currently working with AWS SDK and DynamoDB in my code but the main problem which I constantly encounter is finding scope of variables if I create an asynchronous chain of events.
This is for my node.js server which will run a telegram bot and retrieve/store data in my AWS DynamoDB. It works with a lot of nested calls and passing on variables but makes the code very complicated.
What I want to achieve is something similar to ASYNC/AWAIT.
async DB(){
let paramsGet = { TableName:'some_table', Key:{"id":some_id} }
let database_item = await docClient.get(paramsGet, function(err,data){
if(err){
console.log(err)
} else {
console.log("SUCCESSFULL GET");
return data //RETURN IT TO VARIABLE
}
}
let paramsPut = {
TableName: "my_table",
Item: {
//THESE VALUES SHOULD WAIT FOR GET TO FINISH
//THEN SEND IT TO DB
"id":database_item.id,
"name":database_item.name,
"value":database_item.value
}
}
docClient.put(paramsPut, function(err,data){
if(err){
console.log(err)
} else {
console.log("SUCCESSFULL PUT");
}
}
}
DB();
When I do this let db_item = await docClient.get(...) and console.log(db_item) it will show a stream of data which doesn't look like anything being returned like data in if(err){ console.log(err) } else { console.log(data)}?
How should I handle this return value? Is it a promise or something else that needs to be parsed? I cannot seem to find the db_item.type..
Almost all AWS JavaScript SDK methods have .promise() function returning a Promise of the called operation.
As await works with Promises, you can use that for your needs:
try {
let res = await docClient.get(paramsGet).promise();
let database_item = res.Item;
console.log("SUCCESSFULL GET", database_item);
} catch(err) {
console.log(err);
}
You can find the description of the structure of the returned object in the documentation.
Similar for .put.

Using a db query as a promise [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I'm trying to use sql queries as promises. I can't seem to get it to work:
query: (sql, args) => {
if (args) sql = mysql.format(sql, args);
return new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
console.log(err);
reject(Error(err.code));
}
connection.query(sql, (err, results) => {
connection.release(); // always put connection back in pool after last query
if (err) {
console.log(err);
resolve([]);
}
resolve(results);
});
});
});
},
And here is the query itself:
async function dbCall(sql, arg) {
let data = await db.query(sql, arg);
console.log(data);
data = data[0];
return data;
}
And here is the pool:
var pool = mysql.createPool({
host: 'localhost',
user: 'user',
password: 'pass',
database: 'db',
});
What I'm trying to do:
I'm trying to have it where it doesn't get hung up on async functions. I want it to return a value throughout a whole async function instead of inside of itself only.
Right now, it isn't working at all. However, when it is I would like row to be defined in my whole function instead of just inside the db.query.
I'm not sure if this makes sense, but if you need more clarification just ask anything.
Well if I understand your questions correctly you're misunderstanding how promises should be handled. Promises make use of a then() function to perform something only after the async request is finsihed.
It reads pretty well in plain English. Perform my async request THEN do something with the data.
Try this:
db.query(userSQL, username).then(res => console.log(res))
Additionally, you could use an async function. This allows use to handle async functions in a similar way to synchronous functions where your code will be executed sequentially without having to worry about chaining and nesting other code inside of then() functions
async function dbCall() {
let data = await db.query(userSQL, username);
console.log(data);
}
As a side note. This was super helpful to me when I was first getting into Promises.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Categories

Resources