the piece of code will not executed in async wait - node.js

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.

Related

Firebase onCall method finishes before code execution completes

I have a rather intensive Node function that includes multiple aync tasks that waits for the previous action to complete prior to going to the next step. It's crucial that the entire task finishes when it is called. I'm seeing issues where the onCall function will end before the code execution finishes. I can see this in the logs, as I'm console logging the various methods called from top to bottom until the function is "complete". The parent function is here:
exports.myHandyFunction = functions.https.onCall((data, context) => {
return new Promise((resolve, reject) => {
const response = async () => {
try {
let result = await some_main_function_elsewhere_in_code();
resolve(result)
} catch (err) {
console.log('parent promise caught error:')
console.log(err)
reject(err)
}
}
response()
})
})
I've increased the function's timeout from 60s to 240s hoping that this is purely a function timeout issue? This is pretty troubling, as I have some complex logic being called that ends up not fully completing. Any help would be greatly appreciated.
Your response function is async. When you call it, you're not awaiting for it's execution. This is leading on the premature end of the oncall method execution.
Instead of wrapping the business logic inside an async function, wrapped inside a promise, you can change the code like this:
exports.myHandyFunction = functions.https.onCall((data, context) => {
return new Promise(async (resolve, reject) => {
try {
let result = await some_main_function_elsewhere_in_code();
resolve(result)
} catch (err) {
console.log('parent promise caught error:')
console.log(err)
reject(err)
}
})
})
Basically, the Promise is declared as async, so we can use the await constructor inside of it. Then, we just have to call the some_main_function_elsewhere_in_code method, awaiting for it.

object Promise on return

Whenever I'm trying to generate random keys from crypto or nanoid (new library) it just returns [object Promise]
async function createCode(length){
if(!length){
return nanoid;
} else {
return nanoid(length);
}
}
// another one for example
async function createCode(){
return await crypto.randomBytes(64).toString('hex');
}
An async function returns a promise by default. Please call await createCode() in another async function or use createCode().then()
All async function return a promise. Always.
So, the caller of an async function has to either use await themselves (from within another async function) or use .then() to get the value out of the promise.
It doesn't look to me like either of your functions benefit from being async. return await someFunc() when someFunc() returns a promise can be done with just return someFunc() just the same. The await is not necessary at all.
FYI, crypto.randomBytes() uses a callback if you want the asynchronous version. If you don't pass it a callback, then it's just a plain synchronous function. Unless you've done something to make a promisified version of that library, it doesn't return a promise.
So, you can just use this:
// another one for example
function createCode(){
return crypto.randomBytes(64).toString('hex');
}
Which you can just call as a regular function:
let randomVal = createCode();
console.log(randomVal);
If you want the asynchronous version and want to use it with promises, then you'd have to promisify it:
// another one for example
function createCode(){
return new Promise((resolve, reject) => {
crypto.randomBytes(64, function(err, val) {
if (err) return reject(err);
resolve(val.toString('hex'));
});
});
}
Then, you can call it:
createCode().then(val => {
console.log(val);
}).catch(err => {
console.log(err);
});

Promises function Use in Nodejs

Can't able to understand the promise function, how to deal with it can anyone explain it through a simple example. Tried it through different sites but got confused in it
You can understand it with this example:
const request = require("request")
function doSomething(url){
//return promise from here
return new Promise(function(resolve, reject) {
request.get(url, function(error, resp, body) {
if (error) {
reject(error);
} else {
resolve(JSON.parse(body));
}
})
})
}
function callDoSomething(){
//initialising a promise
let prom = doSomething(url)
//consume it
prom.then(function(res) {
console.log(res)
})
.catch(function(e){
console.log(e.message)
})
}
callDoSomething()
You can also go for Promise.all to deal with multiple promise:
let prom1 = doSomething(url1)
let prom2 = doSomething(url2)
let prom3 = doSomething(url3)
Promise.all([prom1,prom2,prom3])
.then(res =>{
//expected output array
console.log(res)
})
.catch(e =>{
console.log(e.message)
})
A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise for the value at some point in the future.
In simple words “A promise is a word taken for some action, the other party who gave the promise might fulfill it or deny it”. In the case of fulfilling, the promise gets resolved, and in another case, it gets rejected.
We can create a promise in JavaScript and use it as an upcoming fact to describe few actions. Promises are kind of design patterns to remove the usage of unintuitive callbacks.

Node.js MongoDb find function ignores wait

I need the callback function of find from Node.js mongodb 3.1.6 to be triggered before the return statement of an async function, however the return statement is called before the callback function even-though there is a wait in front.
async function(myId) {
const myObject = MyObject()
await collection.find({where: {id: myId}}, async (err, results) => {
if (err) {
logger.error('error');
}
myObject.add(results);
});
return myObject
}
I have seen some examples where instead of find(query, callback) the pattern find(query).toArray() was used. But this doesn't run at all in my case. We use Node.js mongodb 3.1.6 with loopback-connector-mongodb maybe this is related to the problem.
If mongo doesn't provide a promise-answering function, then promisify this one yourself. Neither that promise-creating wrapper nor the anonymous callback it uses should be declared async, but the caller should....
function findById(collection, myId) {
return new Promise((resolve, reject) => {
collection.find({where: {id: myId}}, (err, results) => {
(err)? reject(err): resolve(results);
});
});
}
// now callers can use the async await pattern...
async someFunction() {
try {
let myId = // ...
let collection = // ...
let results = await findById(collection, myId);
// do something with results
} catch (err) {
// error
}
}
The key idea is that collection.find with the callback isn't eligible for await, because it doesn't return a promise. The anonymous callback function you pass to it isn't an async function... it does its work right away, as soon as find calls it back. So we build a promise around mongo, then use the new async/await syntax with that promise.

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

Resources