0

I am really getting a headache trying to make use of the async/await functionality when using for loops. I am using Node.js version: v8.6.0

In short, I am trying to retrieve many rows from a database and then push them all to an array and return that array.

I have successfully done this using callbacks but can't figure out how to do it with async/await.

My current code using callbacks that works

function main(db) {
    gatherDates(db, function(dates) {
        console.log(dates); //successful
    });
}

function gatherDates(db, callback) {
    const dates = [];
    let today = getToday();

    dates.push(today);

    let dateQuery = "SELECT date FROM event_dates";

    db.query(dateQuery, (err, newDates) => {
        for(let row of newDates) {
            dates.push(row.date);
        }
        callback(dates);            
    });
}

The code that fails trying to use async/await

async function main(db) {
    let dates = await gatherDates(db);
    console.log(dates); //undefined or not all of the data
}

function gatherDates(db) {
    const dates = [];
    let today = getToday();

    dates.push(today);

    let dateQuery = "SELECT date FROM event_dates";

    db.query(dateQuery, (err, newDates) => {
        for(let row of newDates) {
            dates.push(row.date);
        }
        return Promise.resolve(dates);
    });
}

I have googled trying to find a solution, I have tried using multiple promise and then calling return Promise.all(promises); at the end but it did not work. I have tried return new Promise((resolve, reject)=>resolve(dates))};. I have looked at Promise and async/await tutorials and examples which usually work for me but when it comes to looping through data that is where I am having an issue. I know there is something fundamental that I am missing so any help is appreciated. Thank you!

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
nd510
  • 113
  • 4

2 Answers2

3

The problem is that you're trying to return the promise from inside the db.query callback, which can't work (and even when you tried to use the promise constructor, you did it inside there, with the same effect as Promise.resolve()). The proper way to promisify is to use new Promise outside, so that you can return it from your outer function, and only put the resolve inside the asynchronous callback.

function query(sql) {
    return new Promise((resolve, reject) {
        db.query(sql, (err, res) => {
            if (err) reject(err);
            else resolve(res);
        });
    });
}

async function gatherDates(db) {
    const dates = [getToday()];
    const newDates = await query("SELECT date FROM event_dates");
    for (let row of newDates) {
        dates.push(row.date);
    }
    return dates;
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

You are not correctly returning a Promise object from your asynchronous function, here is the solution:

function gatherDates(db) {
    const dates = [];
    let today = getToday();
    dates.push(today);
    let dateQuery = "SELECT date FROM event_dates";

    return new Promise((resolve) => {
        db.query(dateQuery, (err, newDates) => {
            for(let row of newDates) {
                dates.push(row.date);
            }
            resolve(dates);
        });
    });
}
M0nst3R
  • 5,186
  • 1
  • 23
  • 36