Обратный вызов выполняется до завершения выполнения функции - PullRequest
1 голос
/ 11 февраля 2020

Здравствуйте, у меня есть эта проблема, всякий раз, когда я выполняю этот код, обратный вызов выполняется до того, как функция de main завершит выполнение. Я считаю, что это как-то связано с асин c функции

var leers3 = async function (next) {
    var executed = [];
    AWS.config.update({
        region: '********',
        accessKeyId: '*********',
        secretAccessKey: '*********'
    });

    var s3 = new AWS.S3();

    s3.listObjects({Bucket:'*******'}, function(err, data) {
        if (err) {
            console.log(fechaActual() + " Error: Error ejecutando cruce con S3.")
        }else{
            var files = [];
            data.Contents.forEach(function(obj,index){
                if(obj.Key.startsWith("*****") || obj.Key.startsWith("*****")){
                    files.push(obj.Key);
                }
            })
            files.forEach((file) => {
                var id_cajero = file.split('_')[1];
                var params = {Bucket:'*****', Key: file};
                var sql = "SELECT id_entidad FROM cajero WHERE id_cajero = '" + id_cajero + "';";
                dbConnection.query(sql, async(err,result) => {
                    if(err) console.log(err);
                    else{
                        var fileExecutedData = await leerarchivos3(params, s3, id_cajero, result[0].id_entidad);
                        fileExecutedData.file = file;
                        executed.push(fileExecutedData);
                        //console.log(executed);    
                    }
                })
                next(executed);                 
            })
        }
    })
};

leers3((executed) => {
        console.log(executed);
    });

Ответы [ 2 ]

2 голосов
/ 12 февраля 2020

forEach не предназначен для обработки / выполнения обещаний и асинхронного кода c. forEach предназначен для синхронной операции. Это означает, что для каждой file, которую вы выполняете итерацию, где, по вашему мнению, выполнение приостанавливается, на самом деле Javascript продолжается до следующей итерации. Вы не сможете гарантировать время выполнения обратных вызовов dbConnection.query. Если вы используете Promise.all с небольшими изменениями вплоть до Array.map, вы можете добиться более предсказуемого результата и использовать «параллельные» возможности, которые дает 1007 *. Вот псевдокод, вдохновленный вашим примером.

    await Promise.all(
        files.map((file) => {
            const id_cajero = file.split("_")[1];
            const params = { Bucket: "*****", Key: file };
            const sql = `SELECT id_entidad FROM cajero WHERE id_cajero = '${id_cajero}';`;

            return new Promise((resolve, reject) => {
                dbConnection.query(sql, async (err, result) => {
                    if (err) {
                        return reject(err);
                    }

                    const fileExecutedData = await leerarchivos3(
                        params,
                        s3,
                        id_cajero,
                        result[0].id_entidad
                    );

                    fileExecutedData.file = file;

                    executed.push(fileExecutedData);

                    return resolve();
                });
            });
        })
    );

    next(executed);
0 голосов
/ 12 февраля 2020

Я бы рекомендовал превратить ваш s3.listObjects вызов в обещание.

const data = await s3.listObjects({Bucket:'*******'}).promise();
// ... do things with the data that is currently in your callback

Я предполагаю, что dbConnection.query также имеет опцию async / await (т.е. Promise).

Если вы должны использовать обратные вызовы, вы должны удалить async из функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...