I'm writing a route that takes in user-input data from a form and uses that data to execute a few separate queries on my database. That is all well-tested, and I know I can get the user input, query the database, and return the results. The part giving me trouble, however, is that I want to randomly select a few results out of all of the returned data, so I am pushing the results into one big array. But since the queries execute asynchronously, the only way to access the data is in the callback and of course if I tried to push the rows in the callback, I still can't access that array outside of the callback functions because that code will execute before the queries are even run. So I'm attempting to use JavaScript async/await syntax to do the queries, as follows:
module.exports = {
search: (req, res) => {
function saveResults(resultsObj) {
Object.keys(resultsObj).forEach(function (key) {
var row = resultsObj[key];
var song = row.song_name
resultsArray.push(song);
return resultsArray;
});
}
async function queryForSong(){
var songGenre;
getSongGenre = "The queries aren't important, I know they work as expected";
await mysqlConnection.query(getSongGenre, (err, rows) => {
if (err) throw err;
songGenre = row[0].song_genre;
songSearchQuery = "SELECT query";
mysqlConnection.query(songSearchQuery, (err, rows) => {
if (err) throw err;
return saveResults(rows);
});
});
}
async function queryForArtist() {
var artistID;
getArtistID = "SELECT query";
await mysqlConnection.query(getArtistID, (err, rows) => {
if (err) throw err;
artistID = rows[0].artist_id;
console.log(rows, artistID);
artistSearchQuery = "SELECT query";
mysqlConnection.query(artistSearchQuery, (err, rows) => {
if (err) throw err;
return saveResults(rows);
});
});
}
async function queryForGenre() {
genreSearchQuery = "SELECT query";
await mysqlConnection.query(genreSearchQuery, (err, rows) => {
if (err) throw err;
return saveResults(rows);
});
}
async function queryForDecade() {
decadeSearchQuery = "SELECT query";
await mysqlConnection.query(decadeSearchQuery, (err, rows) => {
if (err) throw err;
return saveResults(rows);
});
}
var resultsArray = [];
var artist = req.body.searchArtist;
var song = req.body.searchSong;
var genre = req.body.searchGenre;
var decade = req.body.searchDecade;
if (song) {
queryForSong().then((value) => console.log(value)); //these all log undefined
}
if (artist) {
queryForArtist().then((value) => console.log(value));
}
if (genre) {
queryForGenre().then((value) => console.log(value));
}
if (decade) {
queryForDecade().then((value) => console.log(value));
}
}
}
Then the idea is to save the resolved rows from the promises into one big array and randomize it from there. My only thought of why this isn't working is that it could be because the return statements are located inside the callback functions? I have also tried it using promises directly as this post explains, by writing all of my async functions like this instead:
function queryForGenre() {
genreSearchQuery = "SELECT query";
return new Promise(function (resolve, reject) {
mysqlConnection.query(genreSearchQuery, (err, rows) => {
if (err) reject(err);
resolve(saveResults(rows));
});
});
}
But either way, the console.log statements in the .then still print undefined, meaning my promises aren't resolving to the saveResults(rows) value that I give it. Do I need to make the saveResults function asynchronous as well? From my understanding of promises, this seems like it should work. What am I missing? Or is there a simpler way to do this?