Проблемы с Async / Await Promise - Javascript / Nodejs

У меня действительно заболела голова, пытаясь использовать функцию async / await при использовании циклов for. Я использую версию Node.js: v8.6.0

Короче говоря, я пытаюсь получить много строк из базы данных, а затем поместить их все в массив и вернуть этот массив.

Я успешно сделал это с помощью обратных вызовов, но не могу понять, как это сделать с помощью async / await.

Мой текущий код, использующий обратные вызовы, работает

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

Код, который не пытается использовать 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);
    });
}

Я искал в Google, пытаясь найти решение, я попытался использовать несколько обещаний, а затем вызвать return Promise.all(promises); в конце, но это не сработало. Я пробовал return new Promise((resolve, reject)=>resolve(dates))};. Я просмотрел учебные пособия и примеры Promise и async / await, которые обычно работают для меня, но когда дело доходит до циклического перебора данных, именно здесь у меня возникает проблема. Я знаю, что мне не хватает чего-то важного, поэтому любая помощь приветствуется. Спасибо!


person nd510    schedule 12.10.2017    source источник


Ответы (2)


Проблема в том, что вы пытаетесь return выполнить обещание из db.query обратного вызова, что не может работать (и даже когда вы пытались использовать конструктор обещаний, вы делали это внутри с тем же эффектом, что и Promise.resolve()). Правильный способ обещания - использовать new Promise снаружи, чтобы вы могли return из своей внешней функции, и только поместите resolve внутри асинхронного обратного вызова.

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;
}
person Bergi    schedule 12.10.2017
comment
отлично поработали! и теперь я понимаю обещания намного лучше. Спасибо - person nd510; 12.10.2017

Вы неправильно возвращаете объект Promise из своей асинхронной функции, вот решение:

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);
        });
    });
}
person Ghassen Louhaichi    schedule 12.10.2017
comment
Вы обязательно должны это сделать, но он просит не об этом, я предпочитаю отвечать точным требуемым поведением. - person Ghassen Louhaichi; 12.10.2017
comment
Я не понимаю, где в его вопросе OP требует использовать плохие методы. - person Bergi; 12.10.2017
comment
Плохая практика? Конечно. - person Ghassen Louhaichi; 12.10.2017