Async Mysql Query in Node.js - javascript

I want to get a specific value from my mysql database and then pass it to an API. So I have to wait for the query to finish. I found this async/await example on stackoverflow. But it's not working for me.
async function getUTC() {
try {
let result = await db.query(`SELECT utcEndSeconds FROM mp_games ORDER BY utcEndSeconds ASC LIMIT 1`)
return result
} catch (err) {
console.log(err)
}
}
let newUTC = getUTC()
console.log(newUTC)
newUTC.then(data => {
console.log(data)
})
The first console.log(newUTC) prints Promise { pending }. I expected to find my data here, because await should already resolve the promise???
Then I added the .then() block. console.log(data) prints a big object (mysql I guess) but my data is nowhere to be found in the object.
What am I missing here? Thanks in advance.

You have problems with understanding of async/await pattern.
newUTC.then(data => {
console.log(data)
})
the above code resolves promise and return you data object. but console.log(newUTC) gives you promise pending because it is not awaited nor encapsulated with promise for resolution.
if you change
let newUTC = getUTC()
console.log(newUTC)
to
let newUTC = getUTC()
console.log(await newUTC)
then first the code awaited and the result is passed to the console.log.
EDIT: await only works within async function. IF your function is not async then you need to use promise approach.
let newUTC = getUTC()
newUTC.then(data => console.log(data));

I think it's easier to use mysql.query callback function and run the rest of my code inside. It's not as pretty but works
db.query(`SELECT utcEndSeconds FROM mp_games ORDER BY utcEndSeconds ASC LIMIT 1`, (err, result) => {
let newUTC = result[0].utcEndSeconds
... rest of my code (api calls etc...)
}

Related

How to get neo4j query result returned from .then with node js

I would need to get the data returned by using the Neo4j driver for Node JS. My problem is, that i can print the value of 'online' out on console inside the .then call but i can't seem to get access to it outside of that part - I have tried returning record.get('onl'), assign it to a pre-defined variable outside the function but nothing works - all i get as result if i try to, for example, print the value of online out at the last line in this snippet, is Promise { <pending> }. I suppose I don't do the promise handling right, and I looked up lots of tutorials and examples, but I can't work it out. So: how could i assign the returned data (record.get('onl')) to var online and get actual result instead of the promise?
Thanks in advance :)
var online = session.run(cyp1, param).then(results => {
return results.records.map(record =>{
console.log(record.get('onl'))
return record.get('onl')
})
}).then(()=>{
session.close()
});
console.log(online)
Currently, you are assigning var online as a 'Promise Chain' & not a 'Resolved Promise'. You could use Async/Await this will allow you to write async code in a synchronous manner.
async function getRecords(){
const records = await session.run(cyp1, param);
return records.map(record => record.get('onl'))
}
const online = await getRecords();
Use try/catch/finally
try {
const online = await getRecords();
} catch (error) {
// do something
} finally {
await session.close()
}
If you wanted to continue using .then()
You need to use 'Promise Chaining' and pass the value 'Down the chain', this results in complex 'Callback'/'Promise Chain' hell.
session.run(cyp1, param).then(results => {
return results.records.map(record => record.get('onl'))
}).then((online)=> {
console.log(online)
}).catch(() => {
// do something
}).finally(() => {
session.close()
});

Continue .map loop after util.promisify request fails in iteration (async await)

I have the below async function taking in an array of 4 objects. The first one is processed in a .map loop that executes a query and results in an error (in the await executeQuery(queryString)). When this first object is completed processing, the loop ends and the other 3 objects are not processed.
async function myFunction(arrayOfObjects, param1) {
const promises = arrayOfObjects.map(async function (currElement, i) {
var queryString = 'www.querystring.com?APIparameter=param1';
const executeQuery = util.promisify(request);
await executeQuery(queryString).then(data => {
//process data here using currElement, i
}).catch(err => console.log('error: ', err));
});
await Promise.all(promises).catch();
}
I originally only had await Promise.all(promises) and thought revising it to await Promise.all(promises).catch(); would do the trick but it is still failing out on the first object iterated.
I was wondering how best to achieve continuing the .map loop after an error hits the catch in the executeQuery.
Please and thank you!
Not 100% sure what's happening with this code but there are a few things I would change. Firstly it's not good practice to use an await inside a loop and secondly, your promises array is probably not what you expect as the await is yielding until each promise is resolved inside the loop. Return the Promise from the map function to generate an array of Promises that will each resolve and process the data in their own time. You can then await all the promises and catch any errors using try/catch. Something similar to the following should do what you are expecting...
async function myFunction(arrayOfObjects, param1) {
const executeQuery = util.promisify(request);
const promises = arrayOfObjects.map((currElement, i) => {
const queryString = 'www.querystring.com?APIparameter=param1';
return executeQuery(queryString).then(data => {
// process data here using currElement, i
});
});
try {
await Promise.all(promises);
// all promises will be resolved here
} catch (err) {
console.log('error: ', err);
}
}

Promise.all results are as expected, but individual items showing undefined

First of all, there are some issues with console.log in Google Chrome not functioning as expected. This is not the case as I am working in VSCode.
We begin with two async calls to the server.
promise_a = fetch(url)
promise_b = fetch(url)
Since fetch results are also promises, .json() will needed to be called on each item. The helper function process will be used, as suggested by a Stackoverflow user -- sorry lost the link.
let promiseResults = []
let process = prom => {
prom.then(data => {
promiseResults.push(data);
});
};
Promise.all is called. The resulting array is passed to .then where forEach calls process on item.json() each iteration and fulfilled promises are pushed to promiseResults.
Promise.all([promise_a, promise_b])
.then(responseArr => {
responseArr.forEach(item => {
process(item.json());
});
})
No argument is given to the final .then block because promiseResults are in the outer scope. console.log show confusing results.
.then(() => {
console.log(promiseResults); // correct results
console.log(promiseResults[0]); // undefined ?!?
})
Any help will be greatly appreciated.
If you are familiar with async/await syntax, I would suggest you not to use an external variable promiseResults, but return the results on the fly with this function:
async function getJsonResults(promisesArr) {
// Get fetch promises response
const results = await Promise.all(promisesArr);
// Get JSON from each response promise
const jsonResults = await Promise.all(results.map(r => r.json()));
return jsonResults
}
This is usage example:
promise_a = fetch(url1)
promise_b = fetch(url2)
getJsonResults([promise_a, promise_b])
.then(theResults => console.log('All results:', theResults))
Use theResults variable to extract necessary results.
You can try this, it looks the array loop is not going properly in the promise env.
Specifically: the promiseResults is filled after you are logging.
var resultAll = Promise.all([promise_a, promise_b])
.then(responseArr => {
return Promise.all(responseArr.map(item => return item.json()));
});
resultAll.then(promiseResults => {
console.log(promiseResults);
});

WHy am I getting a SyntaxError: Unexpected identifier in forEach with await?

I have an object with a series of named SQL query templates that I'm trying to execute.
The query() method is async, so I should be able to run it with await, but I get an Unexpected identifier error. If I take off the await, then I don't get an error, but I'm stuck with a Promise object...
Object.entries(sqlquerries).forEach(([queryName, queryTpl]) => {
try {
const querystr = replVars(queryTpl, vars);
report[queryName] = await query(querystr);
} catch (err) {
console.error('An error occured running the query : ', err );
}
});
return report;
Why would that be? What can I do to construct my report object and get around this error?
Any help/pointers would be greatly appreciated.
Because the function await appears in (the forEach callback) isn't an async function. If you make it one, beware that forEach does nothing with the callback's return value, which will be a promise if it's an async function, and so you need to be sure to handle errors inline (which you're doing).
But, your return report suggests you're expecting to wait for this process to complete. Beware that forEach will not wait for the previous iteration's promise to resolve before proceeding with the next. If you want to do that, use the promise reduce trick instead and await the result (I assume this is all in an async function):
await Object.entries(sqlqueries).reduce((p, [queryName, queryTpl]) => {
const querystr = replVars(queryTpl, vars);
return p.then(async() => {
report[queryName] = await query(querystr);
});
}, Promise.resolve());
return report;
Or if you can run the queries in parallel, use map and Promise.all instead, and again await the result:
await Promise.all(Object.entries(sqlqueries).map(async ([queryName, queryTpl]) => {
const querystr = replVars(queryTpl, vars);
report[queryName] = await query(querystr);
}));
return report;

async/await and templating with pug

I'm new to using async/await in nodejs and am confused about how to return data that I want for use in a view. Here is my code. below is the homeController, which is used like so:
app.get("/", homeController.index);
I tried making the index method async, but i still can't console out the news data. what is the right way to resolve the article information so it's available for consumption in the view in home?
async function getNewsData() {
const pool = await connection;
const result = await pool.request()
.input("StoryID", sql.Int, 154147)
.execute("News.uspStoryByIdGet");
console.log(result, "the result from the stored procedure");
return result;
}
const article = getNewsData().
catch((e) => {
console.log("the error", e);
});
export let index = async(req: Request, res: Response) => {
const article = await getNewsData();
console.log(article, "yoo");
res.render("home", {
article,
title: "Home",
});
};
for what I can see you should probably not be awaiting for connection in your getNewsData unless for some reason connection is a promise that is was or is waiting to be resolved.
you should also be returning result on getNewsData function.
If that is not what is causing the problems there here are some clarifications about async/await
1 - Calling an async function behaves similar to calling a function that returns a Promise
2 - when you use await its behaves as if you wait for a promise to be resolved and extract the result from it, which you would have in your scope instead of having passed to a callback function in the then or catch methods.
feel free to reply to this answer if still in doubt.
No value is returned fromgetNewsData() function call, see Why is value undefined at .then() chained to Promise? You can return row from getNewsData() if expected result of getNewsData() call is rows array.

Categories