How to get Entities synchronously while using Nodejs - node.js

I'm trying to get storage account's Table's data.
I succeed in getting the date using the way here.
But it's using callback. I want to get the results synchronously!

You can write a helper function which returns Promise to make it synchronous (or simulate it)
function getSome(mytable, hometasks, num)
return new Promise((resolve, reject) => {
tableSvc.retrieveEntity(mytable, hometasks, num, function(error, result, response){
if(!error){
resolve(entity // result or response etc)
} else {
reject(error)
}
});
})
Then you can use elsewhere in your code with async/await (to pause execution) like
Note you can use await only inside async function
async function useData() {
const data = await getSome('mytable', 'hometasks', '1');
// use data here
}
or with plain promise as (Note, this does not pause execution, code inside then is a callback function again)
const data = getSome('mytable', 'hometasks', '1');
data.then(res => // do something)
Also looks like cosmos have now sdk with Promise support.
Read more about Promise and async/await on MDN

Related

the piece of code will not executed in async wait

the piace of code with if condition will not executed and the parent function will be executed after promise, but I dont understand why
let sql = `SELECT *
FROM ${table}
WHERE trader = '${trader}'
AND pair = '${data.symbol}'`;
console.log(sql)
let resp = await new Promise((resolve, reject) => {
db.all(sql, function (err, rows) {
console.log("err2")
console.log(err)
console.log("rows2")
console.log(rows)
return resolve(rows)
})
})
if (resp[0]) { // <------- this will be executed after
if (data.amount > resp[0].amount) {
console.log('amount cambiato, comprato')
// BUY Position
await updatePosition(data, trader, 'buy');
}
if (data.amount < resp[0].amount) {
console.log('amount cambiato, sellato')
// BUY Position
await updatePosition(data, trader, 'sell');
}
if (data.amount == resp[0].amount) {
// BUY Position
console.log('amount IDENTICO');
await setCheckedTraderCoin(trader, data.symbol)
}
}
why this?
This has to be in an async function since you're using await. Thus, it returns a promise.
So, the caller must use await or .then() on that returned promise so it will also wait for the work to be done here.
ALL async functions return their promise upon the first await in the function. That's why the caller has to also wait for that promise to resolve - otherwise it runs off and executes before any of the asynchronous work in this function is complete (as you've observed).
So, the solution to your caller running before the asynchronous work in this function has completed is for the caller to wait (using either .then() or await) for the returned promise to resolve before it does anything further.
Also, you need error handling on the promise that wraps db.all() so you reject that promise if there's an error:
let resp = await new Promise((resolve, reject) => {
db.all(sql, function (err, rows) {
if (err) {
reject(err);
} else {
resolve(rows)
}
});
});
FYI, it would be preferable to use a driver for your database that directly supports promises so you don't have to manually wrap each call in a promise yourself. Most database interfaces support promises by now. Sometimes, you need a different version of the driver - sometimes it's already available in the one you're using. It depends upon which database/driver you are currently using.

My async/await function is not waiting in AWS Lambda. What am I missing?

I have a function in AWS Lambda to retrieve user details in Stripe. But the code after the function is executing first. What am I missing?
In my case, the function calls a Stripe function that returns a customer object.
I think the details of the Stripe function are not relevant for this specific question--the issue is the structure of my async/await:
module.exports.getUserName = async (event, context)=>{
[code to get customerId from stripe]
var customerName
await stripe.customers.retrieve(customerId, function(err, customer){
if (err){}
else{
customerName = customer.name
}
})
console.log('This should run after stripe.customers.retrieve')
}
Right now the console.log statement runs first. I've also tried wrapping the Stripe function in a separate async function, and also tried adding try/catch. But it's not working yet.
How can I be sure that the console log statement instead runs after stripe.customers.retrieve ?
Edit:
I checked the source for the npm stripe package. All the functions do return Promises, but if you additionally supply a callback, they're scheduled to be called on the next event loop (immediately after your console.log runs).
All you need to do is simply don't provide a callback if you'll be using the promise. Use Promise.then() instead:
await stripe.customers.retrieve(customerId).then(customer => {
customerName = customer.name
resolve()
}).catch(_=>{})
Old answer (still works, but very redundant):
await is to be used with Promises, it doesn't magically convert asynchronous code to synchronous. I can see from the old-fashioned function(err, customer){ callback that your stripe.customers.retrieve() function does not return a Promise, so the await won't actually do anything.
You need to wrap it in a promise in order to use with async/await:
await new Promise((resolve,reject) => {
stripe.customers.retrieve(customerId, function(err, customer) {
if(!err) {
customerName = customer.name
resolve()
}
})
})

API Call using a Promise or Async returning a variable with the data

NB:I am new to Node.js
I would like to call a function in the current module and it perform the data pull with a promise or async function. Then be able to access the data in a variable. Once it is a variable out of the promise maybe I can store/use/investigate the data. Any help would be much appreciated.
I manged to get the code below to run but I am not really sure if it is correct? Is there a cleaner/proper way to do this? Very confused.
I have tried to write a promise but I am going in circles.
const publicClient = new CoinbasePro.PublicClient();
const coinbasePro = require('coinbase-pro')
const p = new Promise((resolve, reject) => {
yourFunction()
async function yourFunction() {
try {
const products = await publicClient.getProducts();
resolve(products);
//console.log('ArrayName', products);
return products
} catch (error) {
reject(error);
}
}
});
p.then(result => console.log('Result', result))
p.catch(err => console.log('Error', err.message));
1) I would like to be able to invoke this promise from the same module and get the data in a variable.
2) I would like to be able to invoke this promise from another module and get the data in a variable.

node.js middleware making code synchronous

I am trying to make res.locals.info available on every single page.
I'm trying to do this by middleware but I'm getting an error.
Apparently res.locals.info is not ready yet when the page render, thus I get an error info is not defined. How do I solve this?
app.use(function(req,res,next){
async function getInfo(user) {
let result = await info.search(user);
setInfo(result);
}
function setInfo(result){
res.locals.info= result;
}
getInfo(req.user);
return next();
})
search():
module.exports.search= function (user) {
var query=`SELECT count(*) as Info from dbo.InfoUsers WHERE user= '${user}' ;`
return new Promise((resolve, reject) => {
sequelize
.query(`${query}`, {model: InformationUser})
.then((info) => {
resolve(info);
})
})
};
You were calling next() before your getInfo() function had done its work, thus res.locals.info had not yet been set when you were trying to use it.
An async function returns a promise. It does NOT block until the await is done. Instead, it returns a promise immediately. You will need to use await or .then() on getInfo() so you know when it's actually done.
If info.search() returns a promise that resolves to the desired result, then you could do this:
app.use(function(req,res,next){
// this returns a promise that resolves when it's actually done
async function getInfo(user) {
let result = await info.search(user);
setInfo(result);
}
function setInfo(result){
res.locals.info= result;
}
// use .then() to know when getInfo() is done
// use .catch() to handle errors from getInfo()
getInfo(req.user).then(result => next()).catch(next);
});
And, you can remove the deferred anti-pattern from your search function and fix the error handling (which is a common issue when you use the anti-pattern). There is no need to wrap an existing promise in another promise.:
module.exports.search = function (user) {
var query=`SELECT count(*) as Info from dbo.InfoUsers WHERE user= '${user}' ;`
// return promise directly so caller can use .then() or await on it
return sequelize.query(`${query}`, {model: InformationUser});
};

NodeJS Express Async issue

I have this function which gets some data from my database but i'm having a trouble calling the function and getting the proper response
function getEvents()
{
var x = [];
var l = dbCollection['e'].find({}).forEach(function(y) {
x.push(y);
});
return x;
});
and another function which calls this function but it always returns undefined.
How can i make the function wait till mongoose has finished filling up the array?
Thanks for the help! My life
dbCollection['e'].find is called non-blocking way so you are returning x before filling. You need to use callbacks or some mongoose promises. You can get all returning values from database like following snippet
function getEvents(callback) {
dbCollection['e'].find({}, function(error, results) {
// results is array.
// if you need to filter results you can do it here
return callback(error, results);
})
}
Whenever you need to call getEvents function you need to pass a callback to it.
getEvents(function(error, results) {
console.log(results); // you have results here
})
You should read mongoose docs for how queries work.
There is also support for promises in mongoose. You can check this url for more information about promises.
The solution proposed by #orhankutlu should work fine.
I will give another solution using promise. You can choose one between these two solutions depending on your style of programming.
Solution using promise:
function getEvents() {
return new Promise(function(resolve, reject){
dbCollection['e'].find({}, function(error, results) {
if (error) return reject(error);
var x = [];
results.forEach(function(y){
x.push(y);
});
// forEach() is a blocking call,
// so the promise will be resolved only
// after the forEach completes
return resolve(x);
});
});
};
Calling getEvents():
getEvents().then(function(result){
console.log(result); //should print 'x'
}).catch(function(err){
// Handle error here in case the promise is rejected
});
I will encourage you to try both the approaches, ie, using callbacks and using promises. Hope you find it useful!

Resources