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

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.

Related

How to handle Firebase Firestore errors with async/await

I've been trying to figure out how to handle Firebase errors for the firestore using async/await. I want to show an error message, if a doc doesn't exist but I'm a little confused about how I would do that with async/await.
getResult.js
If I purposely give a fake document ID, the catch function automatically takes over and I can no longer access result.exists which is what I need in this case.
Is there a way I can easily check what type of error it is when I catch it, so I can return an appropriate message?
export const getResult = async (collection, doc) => {
try {
const resultRef = db.collection(collection);
const result = await resultRef.doc(doc).get();
if (result.exists) {
return { data: result };
} else {
return { data: "Error retrieving document, as it doesnt exist" };
}
} catch (err) {
if (err.response) {
console.log(err.response.data);
return err.response.data;
} else if (err.request) {
console.log(err.request);
return err.request;
} else {
console.log(err.message);
return err.message;
}
}
};
Is there a way I can easily check what type of error it is when I catch it?
The only piece of information you will get is the err object. We can't see what that is for your specific case, because we can't run your code. But it's what you'll have to use that object to figure out what the problem is and how to resolve it. These exception objects don't have a "type". You have to look at the contents of the object to understand what went wrong.
You might want to read up on exception handling in JavaScript. It is the same for all promises in JavaScript. Firestore is no different.

How do I return a value in a promise? (Firebase.get())

I've been struggling for the past four hours on this. I am writing a function to see if a property named "data" exists in my Firebase storage. If it does, I want to do one thing, if it doesn't I want to do something else. However, I cannot figure out how this asynchronous stuff works for the life of me. I simplified my code below. Basically I just want to wait for the data to be fetched before I reach the if/else. I've been playing around with different options but keep getting errors or some other issue. The code below is the closest I've gotten to working where the code doesn't crash but even if "data" does not exist in the Firestore, I'm always going through the else clause and I don't know why. Can someone help me figure out what I am doing wrong?
const fetchDataFromDB = async (user) => {
let query = db
.collection("users")
.doc(user)
.get()
.then((doc) => {
doc.data();
console.log(doc.data().data);
});
return await query;
};
export const getSchedule = (miles, user) => {
const firebaseData = fetchDataFromDB(user);
console.log(firebaseData);
// WAIT FOR FETCH BEFORE CONTINUING
if (!firebaseData) {
console.log("NOT getting data from FB");
return;
} else {
console.log("getting data from FB");
return;
}
};
Change up the code as follows:
const fetchDataFromDB = (user) => {
return db
.collection("users")
.doc(user)
.get()
.then((doc) => {
const data = doc.data();
console.log(data);
return data;
});
};
export const getSchedule = async (miles, user) => {
const firebaseData = await fetchDataFromDB(user);
console.log(firebaseData);
if (!firebaseData) {
console.log("NOT getting data from FB");
return;
} else {
console.log("getting data from FB");
return;
}
};
The point to remember about async await is that it doesn't really make asynchronous calls synchronous, it just makes them look that way so that your code is a bit less unwieldy with wrapped promises and the like. Every async function returns a promise, so if you want to deal with what it returns, you need to either deal with the promise directly (using .then...), or by using another await. In the latter case, you of course need to declare the consuming function as async as well.
With regards to the first function, there's no need for the async await there. Just return the promise. (Thanks #charlieftl for pointing out the problem in that code)

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()
}

Can't use a variable from an await mongodb query

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);
}

Mongodb find() returns undefined (node.js)

Ive been playing around with mongodb in node.js. I have made a basic collection with some data (i know its there ive checked). When I try to run a find() on the collection it returns undefined. I dont know why this is. The code is below:
function get_accounts(){
var MongoClient = mongodb.MongoClient;
var url = "url";
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
//HURRAY!! We are connected. :)
console.log('Connection established to database');
var collection = db.collection('accounts');
collection.find().toArray(function(err, docs) {
console.log("Printing docs from Array")
docs.forEach(function(doc) {
console.log("Doc from Array ");
console.dir(doc);
});
});
console.log("mission complete");
}
db.close();
}
);
}
If you know why this is happening i would like to hear your thoughts. thanks! The database is a mongolab hosted database if that makes any difference.
You are getting an undefined value because of the asynchronous nature of node.js, nowhere in your code exists logic that tells the console.log statement to wait until the find() statement finishes before it prints out the documents. You have to understand the concept of callbacks in Node.js. There are a few problems here, though, that you could fix. A lot of people getting started with node have the tendency to nest lots of anonymous functions, creating the dreaded "pyramid of doom" or callback hell. By breaking out some functions and naming them, you can make it a lot cleaner and easier to follow:
var MongoClient = require("mongodb").MongoClient
// move connecting to mongo logic into a function to avoid the "pyramid of doom"
function getConnection(cb) {
MongoClient.connect("your-mongo-url", function(err, db) {
if (err) return cb(err);
var accounts = db.collection("accounts");
cb(null, accounts);
})
}
// list all of the documents by passing an empty selector.
// This returns a 'cursor' which allows you to walk through the documents
function readAll(collection, cb) {
collection.find({}, cb);
}
function printAccount(account) {
// make sure you found your account!
if (!account) {
console.log("Couldn't find the account you asked for!");
}
console.log("Account from Array "+ account);
}
// the each method allows you to walk through the result set,
// notice the callback, as every time the callback
// is called, there is another chance of an error
function printAccounts(accounts, cb) {
accounts.each(function(err, account) {
if (err) return cb(err);
printAccount(account);
});
}
function get_accounts(cb) {
getConnection(function(err, collection) {
if (err) return cb(err);
// need to make sure to close the database, otherwise the process
// won't stop
function processAccounts(err, accounts) {
if (err) return cb(err);
// the callback to each is called for every result,
// once it returns a null, you know
// the result set is done
accounts.each(function(err, account) {
if (err) return cb(err)
if (hero) {
printAccount(account);
} else {
collection.db.close();
cb();
}
})
}
readAll(collection, processAccounts);
})
}
// Call the get_accounts function
get_accounts(function(err) {
if (err) {
console.log("had an error!", err);
process.exit(1);
}
});
You might have to add an empty JSON object inside the find.
collection.find({})
Documentation can be found here.
You must enter this code in an async function and you will be fine here data is the your desired value and you must use promises to not make your code look messy.
var accountCollection = db.collection('accounts);
let data = await accountCollection.find().toArray.then(data=>data).catch(err=>err);

Categories

Resources