async keyword not working on function using node js - javascript

I don't know why i am getting this error
uncaughtException: await is only valid in async function
as i am using async keyword at getChild function still i am getting this error
my code:
async function filterFile(folderPath) {
try {
wantExt = [".jpg"];
let parts;
const paths = await checkFileLoc(folderPath, 3);
const otherFiles = [];
for (const filePath of paths) {
parts = filePath.split("/");
let splitFileName = parts[parts.length - 1].split(".");
if (wantExt.includes(`.${splitFileName[splitFileName.length - 1]}`)) {
otherFiles.push(filePath);
}
}
let ignoreFile = otherFiles.filter((x) =>
x.endsWith("_bio.jpg")
);
let test = otherFiles.filter((x) => !ignoreZipFile.includes(x));
return { test };
} catch (error) {
console.log("error:", error);
}
}
async function getChild(parents) {
return new Promise(function (resolve, reject) {
Shop.findAll({
where: {
shop_no: parents.id,
},
attributes: ["id", "name"],
})
.then((children) => {
let gotValue= await filterFile(children);
console.log(gotValue);
resolve(children);
})
.catch(function (err) {
reject(err);
});
});
}
and if i remove async from the function then I am getting gotValue as promise don't know how to get value

Try adding async to callback function in findAll
async function getChild(parents) {
return new Promise(function (resolve, reject) {
Shop.findAll({
where: {
shop_no: parents.id,
},
attributes: ["id", "name"],
})
.then(async (children) => { // Add it here
let gotValue= await filterFile(children);
console.log(gotValue);
resolve(children);
})
.catch(function (err) {
reject(err);
});
});
}

You missed async keyword before
(children) => {
let gotValue = await filterFile(children);
console.log(gotValue);
resolve(children);
}
function. It should be
async (children) => {
let gotValue = await filterFile(children);
console.log(gotValue);
resolve(children);
}

"await is only valid in async function"
Exactly as the error says, await is used inside an async function.
const fn = async () => { await someAsyncFunction() };
So in your scenario, make the callback async as well to await the filterFile code.
.then(async (children) => {
let gotValue= await filterFile(children);
console.log(gotValue);
resolve(children);
})

async function filterFile(folderPath) {
try {
wantExt = [".jpg"];
let parts;
const paths = await checkFileLoc(folderPath, 3);
const otherFiles = [];
for (const filePath of paths) {
parts = filePath.split("/");
let splitFileName = parts[parts.length - 1].split(".");
if (wantExt.includes(`.${splitFileName[splitFileName.length - 1]}`)) {
otherFiles.push(filePath);
}
}
let ignoreFile = otherFiles.filter((x) =>
x.endsWith("_bio.jpg")
);
let test = otherFiles.filter((x) => !ignoreZipFile.includes(x));
return { test };
} catch (error) {
console.log("error:", error);
}
}
async function getChild(parents) {
try {
const children = await Shop.findAll({
where: {
shop_no: parents.id,
},
attributes: ["id", "name"],
});
let gotValue= await filterFile(children);
console.log(gotValue);
return children;
} catch(err) {
throw(err);
}
}

Related

Promise.all with "nested" axios request

I'm facing a small problem with Promise.all and axios. I read a lot of documentation on "how to do it", but still I did not get what I want.
Basically, I want to execute multiple axios requests and when they all finished, I want to do something…
My code is:
async ajaxPromise() {
let me = this;
const someFunction = () => {
return new Promise(resolve => {
setTimeout(() => resolve('222'), 100)
})
}
async function asyncForEach(array, callback) {
for (let index = 0; index < array.length; index++) {
debugger;
await callback(array[index], index, array);
}
}
let urlObjects = ["https://url1.com", "https://url2.com", "https://url3.com"];
let requestArr = [];
await asyncForEach(urlObjects, async (data) => {
let waitForThisData = await someFunction(data);
requestArr.push(
axios.get(data)
.then(function (response) {
console.log("THEN AXIOS")
})
.catch(function (response) {
console.log("CATCH AXIOS")
})
);
});
Promise.all([
requestArr
])
.then(function (results) {
console.log("THEN PROMISE")
})
.finally(() => {
console.log("FINALLY PROMISE")
})
.catch(function (error) {
console.log("CATCH PROMISE")
});
},
What happens, is console.log("THEN PROMISE") is displayed before all the console.log("THEN AXIOS"). What I would like to do: display the console.log("THEN PROMISE") after the console.log("THEN AXIOS").
Where am I wrong ?
Thanks for your help.

How to return data from RabbitMQ consume function in nodejs?

I have consume function like this.
In this case when i put console.log() in consume callback function, i see messages coming from queue.
Function 1
async function consumeData() {
try {
const connection = await amqp.connect("amqp://localhost:5672");
const channel = await connection.createChannel();
await channel.assertQueue(queueName);
let consumedData;
channel.consume(queueName, (message) => {
consumedData = message.content.toString();
console.log(consumedData);
channel.ack(message);
});
} catch (error) {
console.log("Error", error);
}
}
But i dont wanna log this data. I wanna return and use it like this.
Function 2
async function consumeData() {
try {
const connection = await amqp.connect("amqp://localhost:5672");
const channel = await connection.createChannel();
await channel.assertQueue(queueName);
let consumedData;
channel.consume(queueName, (message) => {
consumedData = message.content.toString();
console.log(consumedData);
channel.ack(message);
});
return consumedData;
} catch (error) {
console.log("Error", error);
}
}
When i run function 2 i cant return any data. How can i return data from this consume function?
return it after trycatch
async function consumeData() {
var consumedData = {};
try {
const connection = await amqp.connect("amqp://localhost:5672");
const channel = await connection.createChannel();
await channel.assertQueue(queueName);
let consumedData;
channel.consume(queueName, (message) => {
consumedData = JSON.parse(message.content.toString());
channel.ack(message);
});
} catch (error) {
console.log("Error", error);
}
return consumedData;
}
and call the function using await
const data = await consumeData();

async function not getting result

I am trying to get the result of an async function in my calculateOrderAmount function but it returns undefined.
The console.log in the called function returns the good result, but inside calculateOrderAmount, I get undefined. Here is my code:
getMultiStrats = async () => {
await MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return err
}
if(!multiStrats) {
return console.log('MultiStrat not found')
}
console.log('returns MultiStrat: ' + multiStrats)
return multiStrats
})
.catch(err => console.log(err))
}
async function calculateOrderAmount(balance, ticker){
const multiState = await StrategyController.getMultiStrats().catch((err) => console.log(err))
console.log('multiState: ' + multiState)
some logic
}
Here is the console log:
multiState: undefined
returns MultiStrat: {
_id: 5ff73c74d1135b39fc709b80,
positionsCount: 1,
inTradeCount: 0,
__v: 0
}
What did I miss? Thanks you very much for your time!
The current approach is pretty unclear--there's no need for .catch, async, await all at once. return multiStrats returns from the inside of the callback, not from getMultiStrats. The async/await on getMultiStrats is superfluous, just adding another promise wrapper that doesn't accomplish anything.
Given that findOne as shown here uses a callback rather than a promise, you can either use callbacks all the way or you can promisify findOne as follows, using .then and .catch in the caller:
const MultiStrats = {
findOne: (obj, cb) => cb(null, "I'm a multistrat!")
};
const StrategyController = {
getMultiStrats: () => new Promise((resolve, reject) =>
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return reject(err);
}
else if (multiStrats) {
return resolve(multiStrats);
}
reject(Error("Multistrat not found"));
})
)
};
const calculateOrderAmount = (balance, ticker) =>
StrategyController
.getMultiStrats()
.then(multiState => {
console.log('multiState: ' + multiState)
// some logic
})
.catch(err => console.error(err))
;
calculateOrderAmount();
Or use async/await and try/catch:
const MultiStrats = {
findOne: (obj, cb) => cb(null, "I'm a multistrat!")
};
const StrategyController = {
getMultiStrats: () => new Promise((resolve, reject) =>
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return reject(err);
}
else if (multiStrats) {
return resolve(multiStrats);
}
reject(Error("Multistrat not found"));
})
)
};
const calculateOrderAmount = async (balance, ticker) => {
try {
const multiState = await StrategyController.getMultiStrats();
console.log('multiState: ' + multiState)
// some logic
}
catch (err) {
console.error(err);
}
};
calculateOrderAmount();
If this is MongoDB's findOne and already returns a promise, then you can just return the promise to the caller, optionally awaiting it and throwing for the null result:
const MultiStrats = {
findOne: async query => "I'm a multistrat!"
};
const StrategyController = {
getMultiStrats: async () => {
const result = await MultiStrats.findOne({});
if (result) {
return result;
}
throw Error("Multistrat not found");
}
};
const calculateOrderAmount = (balance, ticker) =>
StrategyController
.getMultiStrats()
.then(multiState => {
console.log('multiState: ' + multiState);
// some logic
})
.catch(err => console.error(err))
;
calculateOrderAmount();
You cannot return values from an inner callback and reach the outer function, I would suggest
1- only use promises
2- wrap your code with promise to be sure that await will return the async result the way you expect to have.
getMultiStrats = async () => {
return new Promise((resolve, reject) => {
MultiStrats.findOne({}, (err, multiStrats) => {
if (err) {
return err
}
if (!multiStrats) {
console.log('MultiStrat not found')
reject('MultiStrat not found')
}
console.log('returns MultiStrat: ' + multiStrats)
resolve(multiStrats);
})
.catch(err => {
console.log(err);
reject(err)
})
})
}
async function calculateOrderAmount(balance, ticker) {
try {
const multiState = await StrategyController.getMultiStrats()
console.log('multiState: ' + multiState)
// some logic
} catch (error) {
console.error(error);
}
}
Assuming that you use mongoose. I suggest using the promise interface like described in the documentation.
const getMultiStrats = async () => {
const query = MultiStrats.findOne({});
let multiStrats;
try {
multiStrats = await query.exec();
} catch (error) {
return error;
}
if (multiStrats) {
console.log("returns MultiStrat: " + multiStrats);
} else {
console.log("MultiStrat not found");
}
return multiStrats;
}
I would personally not return the error, but instead just let the error be thrown. With the above code the caller of getMultiStrats has to figure out if there return value is the expected result or an error. If you don't catch the error, it is thrown further up to the caller.
const getMultiStrats = async () => {
const multiStrats = await MultiStrats.findOne({}).exec();
if (multiStrats) {
console.log("returns MultiStrat: " + multiStrats);
} else {
console.log("MultiStrat not found");
}
return multiStrats;
}
You can further simplify this if you where to leave the console.log of of the equation.
const getMultiStrats = () => MultiStrats.findOne({}).exec();

async await retry log after all retries

How can I console.log if it still fails after all retries done? and console.log if it succeeds, using async-retry package:
const retry = require('async-retry');
async function updateDB(updateUser) {
await retry(async () => {
const res = await updateUser;
if (/* some error after finishing all retries*/) {
console.log('failed');
}
console.log('Success');
}, {
retries: 5
});
}
how can this be achieved?
or in other words, how can I call another function (function A) only after all retries attempts failed? and call function B if it didn't throw at all.
const retry = require('async-retry');
async function updateDB(updateUser) {
try{
const result = await retry(async () => {
const res = await Promise.all(updateUser).then(()=>{
try{
return new Promise((resolve) => resolve('OK')), { retries: 5 }
}catch(e){
return new Promise((resolve) => resolve('KO')), { retries: 5 };
}
});
}
);
}catch(err){
console.log('The function execution failed !')
}
}
you can use function onRetry, something like this
const retry = require('async-retry');
async function updateDB(updateUser) {
await retry(async () => {
const res = await test();
console.log('Success');
}, {
onRetry: (err, number) => {
console.log('attempt', number)
if (number === 5) {
console.log(err)
}
},
retries: 5
});
}
Have you tried something like:
const result = await retry(async () => {
const res = await updateUser;
if (/* some error after finishing all retries*/) {
console.log('failed');
}
console.log('Success');
return 'success';
}, {
retries: 5
});
if (result != 'success') {
console.log('all failed');
}

Trying to use await with promise in my code here - how to?

I've tried but failed in grasping clearly how javascript promises and await work! I somehow managed to cobble together a function that performs what I need in my node.js micro service, but I'm not sure if I'm doing it the right (optimal) way. Also, I achieved what I wanted using promise without await, but also I haven't done any extensive testing of my code to see if it is indeed running exactly the way I think it is. Here is my code that I currently have and works, but I'm not sure if I'm missing using await for proper functioning:
const QryAllBooks = {
type: new GraphQLList(BookType),
args: {},
resolve(){
return new Promise((resolve, reject) => {
let sql = singleLineString`
select distinct t.bookid,t.bookname,t.country
from books_tbl t
where t.ship_status = 'Not Shipped'
`;
pool.query(sql, (err, results) => {
if(err){
reject(err);
}
resolve(results);
const str = JSON.stringify(results);
const json = JSON.parse(str);
const promises = [];
for (let p = 0; p < results.length; p++){
const book_id = json[p].bookid;
const query = `mutation updateShipping
{updateShipping
(id: ${book_id}, input:{
status: "Shipped"
})
{ bookid
bookname }}`
promises.push(apolloFetch({ query }));
}
//I need an await function so that previous apolloFetch
//goes in sequence of bookid, one after the other
Promise.all( promises ).then(( result) => {
errorLogger(27, 'Error', result);
})
.catch(( e ) => {
errorLogger( 29, 'Error', e );
)};
});
});
}
};
module.exports = {
QryAllBooks,
BookType
};
Avoid the Promise constructor antipattern - you should not be doing anything after the call to resolve inside the promise executor. Put all that stuff in a then callback on the new Promise:
resolve() {
return new Promise((resolve, reject) => {
let sql = singleLineString`
select distinct t.bookid,t.bookname,t.country
from books_tbl t
where t.ship_status = 'Not Shipped'
`;
pool.query(sql, (err, results) => {
if(err) reject(err);
else resolve(results);
});
}).then(results => {
const str = JSON.stringify(results);
const json = JSON.parse(str);
const promises = [];
for (let p = 0; p < results.length; p++){
const book_id = json[p].bookid;
const query = `mutation updateShipping {
updateShipping(id: ${book_id}, input:{
status: "Shipped"
}) { bookid
bookname }
}`;
promises.push(apolloFetch({ query }));
}
return Promise.all(promises);
}).then(result => {
errorLogger(27, 'Result', result);
return result;
}, err => {
errorLogger(29, 'Error', err);
throw err;
)};
}
You can now replace those then calls with await syntax. And also exchange the Promise.all for a sequential awaiting in the loop:
async resolve() {
try {
const results = await new Promise((resolve, reject) => {
// ^^^^^
let sql = singleLineString`
select distinct t.bookid,t.bookname,t.country
from books_tbl t
where t.ship_status = 'Not Shipped'
`;
pool.query(sql, (err, results) => {
if(err) reject(err);
else resolve(results);
});
});
const promises = results.map(res => {
const book_id = res.bookid;
const query = `mutation updateShipping {
updateShipping(id: ${book_id}, input:{
status: "Shipped"
}) { bookid
bookname }
}`;
return apolloFetch({ query });
});
const result = await Promise.all(promises);
// ^^^^^
errorLogger(27, 'Result', result);
return result;
} catch(err) {
errorLogger(29, 'Error', err);
throw err;
}
}
async resolve() {
const results = await new Promise((resolve, reject) => {
// ^^^^^
let sql = singleLineString`
select distinct t.bookid,t.bookname,t.country
from books_tbl t
where t.ship_status = 'Not Shipped'
`;
pool.query(sql, (err, results) => {
if(err) reject(err);
else resolve(results);
});
});
const fetches = [];
for (let p = 0; p < results.length; p++){
const book_id = results[p].bookid;
const query = `mutation updateShipping {
updateShipping(id: ${book_id}, input:{
status: "Shipped"
}) { bookid
bookname }
}`;
fetches.push(await apolloFetch({ query }));
// ^^^^^
}
return fetches;
}

Categories