I get data in callback function of s3.upload but I want to get data outside the loop. Whenever I print ImageArray , it prints empty and after that , The values that comes from AWS gets printed but in delay. The data from AWS doesn't come quickly. It takes time. But I want to wait for all the data to come then continue the rest of the code. I want to store it in array outside of loop. How to do it?
app.post( "/api/readingsources/new", upload.array("image", 10),
async(req, res) => {
let ImageArray = [];
for (let index in Images) {
const s3 = new AWS.S3({ apiVersion: "2006-03-01" });
const temp = s3.upload({
ACL: "public-read",
Bucket: keys.S3ImageBucket,
Key: `${readingGradeLevel}/${sourceName}-${Date.now()}.${
Images[index].mimetype.split("/")[1]
}`,
Body: Images[index].buffer,
ContentType: Images[index].mimetype,
ServerSideEncryption: "AES256",
},
async(err, data) => {
if (err)
return res.status(500).send(`Server error: ${err.message}`);
const location = await data.Location;
console.log(data.Location);
ImageArray.push(data.Location);
}
);
}
console.log(ImageArray);
}
);
CodePudding user response:
I think the easiest way is to promisify the response from s3.upload
and store the promises in an array. Then, outside the for loop, you await for all results (which allows for parallel execution while awaiting inside the for loop forces sequential operations).
That's what it would look like:
async (req, res) {
let ImageArray = [];
let promises = [];
for (let index in Images) {
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });
promises.push(
new Promise((resolve, reject) => {
s3.upload(
{
ACL: 'public-read',
Bucket: keys.S3ImageBucket,
Key: `${readingGradeLevel}/${sourceName}-${Date.now()}.${
Images[index].mimetype.split('/')[1]
}`,
Body: Images[index].buffer,
ContentType: Images[index].mimetype,
ServerSideEncryption: 'AES256',
},
(err, data) => {
if (err) {
reject(err);
} else {
resolve(data.Location);
}
}
);
})
);
}
ImageArray = await Promise.allSettled(promises);
console.log(ImageArray);
}
Note that you will have to decide what you want to do in case of an error. Promise.allSettled
will return an array of all promises but you may not want to throw a 500 error if some of your uploads worked... That's up to you to handle this case.