在for循环中等待异步功能

时间:2019-03-30 02:05:37

标签: node.js async-await es6-promise

我需要等待数组中每个对象的异步方法(对数据库的调用)。现在我有一个for循环,遍历数组,在每个对象上调用async方法。异步功能成功,但是我需要等待每个异步调用完成后才能继续。通过做一些研究,我发现Promises结合await或其他方法可以解决我的问题,但是我一直无法弄清楚。这是我现在拥有的代码。

这是我的带有异步功能的课程

Vacation : class Vacation {
    constructor(id, destination, description, attendee_creator_id) {
        this.id = id;
        this.destination = destination;
        this.description = description;
        this.attendee_creator_id = attendee_creator_id;
        this.creator = undefined;
        this.votes = undefined;
    }
    find_creator(pool){
        return new Promise(function (resolve, reject) {
            var self = this;
            var query = "SELECT * FROM vacation_attendee WHERE id = " + self.attendee_creator_id;
            pool.query(query, function(error, result) {
                if (error) {
                    console.log("Error in query for vacation creator " + error);
                    return reject(error);
                }
            var creator = new attendee.VacationAttendee(result.rows[0].full_name, result.rows[0].email, result.rows[0].password_hash);
            self.creator = creator;
            console.log("creator found ----> " + self.creator.full_name + "in " + self.destination);
            resolve(true);
        });
      })
    }

这是我调用异步功能的方式

function get_all_vacations(callback) {
        var sql_vacations_query = "SELECT * FROM vacation";    
        pool.query(sql_vacations_query, function(error, vacations_query_result) {        
            if (error) {
                console.log("error in vacations query " + error);
                callback(error);
            }
            var all_complete = loop_through_vacations(vacations_query_result.rows, pool);
            callback(null, all_complete);
            });
    }


async function loop_through_vacations(vacations_incomplete, pool) {
    var all_vacations = [];
    for (var vacation_data of vacations_incomplete) {
        var vacation_at_index = new vac.Vacation(vacation_data.id, vacation_data.destination, vacation_data.description, vacation_data.attendee_creator_id);            
        vacation_at_index.find_creator(pool)
            .then(()=> {
                all_vacations.push(vacation_at_index);
            })
            .catch(error=> {
                console.log(error);
            });
        console.log("passed vacation " + vacation_at_index.destination);
    }
    return await Promise.all(all_vacations);
}

3 个答案:

答案 0 :(得分:0)

对我来说,您可以尝试重新设置SQL查询的格式,该代码将更加整洁,并且一次进行大型查询所花的时间少于多个查询。

如果我了解您数据库中的联接:

SELECT * 
FROM vacation_attendee AS attendee 
INNER JOIN vacation ON vacation.attendee_creator_id = attendee.id
-- WHERECLAUSEYOUWANT

然后:

async function get_all_vacations(callback){
    const allComplete = await makeThatBigQuery(); // + treat data as you want
    callback(null, allComplete);
}

在get_all_vacations的定义中,您不必等待all_complete,因此在all_complete准备好之前调用回调函数

答案 1 :(得分:0)

您以错误的方式进行操作,for-loop中没有等待任何事情。

return await Promise.all(all_vacations);不起作用,因为all_vacations不是Promise数组。

在您的情况下,我们有很多方法可以做到这一点,以我的方式为例:创建一个数组来存储所有在您的for-loop中创建的promise,然后等到{ {1}}语法。

Promise.all

我不知道您为什么将async function loop_through_vacations(vacations_incomplete, pool) { var all_vacations = []; var promises = []; // store all promise for (var vacation_data of vacations_incomplete) { var vacation_at_index = new vac.Vacation(vacation_data.id, vacation_data.destination, vacation_data.description, vacation_data.attendee_creator_id); promises.push( // push your promise to a store - promises vacation_at_index.find_creator(pool) .then(() => { all_vacations.push(vacation_at_index) }) .catch((err) => { console.log(err); // Skip error??? }) ); } await Promise.all(promises); // wait until all promises finished return all_vacations; } async/await风格结合使用,在任何情况下我都建议使用callback

混合风格:

async/await

function get_all_vacations(callback) { var sql_vacations_query = "SELECT * FROM vacation"; pool.query(sql_vacations_query, async function(error, vacations_query_result) { // async if (error) { console.log("error in vacations query " + error); return callback(error); // return to break process } var all_complete = await loop_through_vacations(vacations_query_result.rows, pool); // await callback(null, all_complete); }); }

async/await

答案 2 :(得分:0)

这是代码的等待/承诺部分的样子:

function get_all_vacations(callback) {
    var sql_vacations_query = "SELECT * FROM vacation";    
    pool.query(sql_vacations_query, async function(error, vacations_query_result) {        
        if (error) {
            console.log("error in vacations query " + error);
            callback(error);
        }
        var all_complete = await loop_through_vacations(vacations_query_result.rows, pool);
        callback(null, all_complete);
    });
}


async function loop_through_vacations(vacations_incomplete, pool) {
    const promises = [];
    for (var vacation_data of vacations_incomplete) {
        var vacation_at_index = new vac.Vacation(vacation_data.id, vacation_data.destination, vacation_data.description, vacation_data.attendee_creator_id);            
        promises.push(vacation_at_index.find_creator(pool));
    }
    return await Promise.all(promises);
}

理想情况下,您应该删除所有回调(不确定pool.query方法是否支持asyn / await)并将整个代码更改为async / await样式。另外,您还应该使用resolve(creator)来解决'find_creator'中的承诺,以便在解决承诺时获得该值。