Reputation: 137
Hello I have this problem, whenever I execute this code the callback is executed before de main function finishes the execution. I believe it has something to do with async functions
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);
});
Upvotes: 1
Views: 255
Reputation: 3823
forEach
is not designed to handle/execute promises & async code. forEach
is designed to be a synchronous operation. This means that for each file
you iterate over, where you think the execution is pausing, in fact, Javascript continues to the next iteration. You won't be able to guarantee the execution time of the dbConnection.query
callbacks. If you use Promise.all
with a little change up to Array.map
you can achieve a more predictable outcome & leverage the 'parallel' capabilities Promise.all
gives. Here is pseudo-code inspired by your example.
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);
Upvotes: 2
Reputation: 8887
I would recommend turning your s3.listObjects
call into a promise.
const data = await s3.listObjects({Bucket:'*******'}).promise();
// ... do things with the data that is currently in your callback
I assume the dbConnection.query
has an async/await (i.e. Promise) option as well.
If you must use callbacks then you should remove the async
from the function.
Upvotes: 0