I have created a function inside my route that will upload all the images into Cloudinary 3rd party library and it will return all the URLs links, and I am pushing all the links in my URLs variable and then the links will be stored into the database.
I want until the links are available on my URLs variable it will not insert into my database. I am confused about how I can do it using async/await or using promises
This is my route with function. I am using node, express, multer.
app.post('/addProduct', async (req, res, next) => {
let urls = [];
async function sendImagesToCloudinary() {
for (let file of req.files) {
await cloudinary.uploader.upload(
file.path,
{
public_id: `${Date.now()}`,
resource_type: 'auto'
}
).then(result => {
//del files after upload on cloudinary
fs.unlink(file.path, function (err) {
if (err) {
console.log(err);
}
});
urls.push(result.url);
})
.catch(err => {
console.log(err);
});
}
res.json(urls);
}
sendImagesToCloudinary();
// Publish on database
const result = await unityMartMediaCollection.insertOne({ urls: urls })
res.json(result)
});
CodePudding user response:
It's worthwhile to (a) tease apart the various async ops into smaller - clearer, testable - functions, and (b) utilize only one style of promise syntax...
// isolated version of he OP upload
async function upload(file) {
const params = { public_id: `${Date.now()}`, resource_type: 'auto' }
return cloudinary.uploader.upload(file.path, params);
}
// this promisify's fs.unlink (probably natively available in fs.promise)
async unlink(file) {
return new Promise((resolve, reject) => {
fs.unlink(file.path, error => error? reject(error) : resolve());
});
}
// upload, then unlink if upload succeeds, return the url upload result
// catch errors here, so other concurrent uploads can continue
async uploadAndUnlink(file) {
try {
const url = await upload(file);
await unlink(file);
return url
} catch (err) {
console.log(err);
}
}
// implement the route, process the files concurrently
app.post('/addProduct', async (req, res, next) => {
const promises = req.files.map(file => uploadAndUnlink(file));
const urls = await Promise.all(promises);
const result = await unityMartMediaCollection.insertOne({ urls: urls })
res.json(result);
});
I took the liberty of removing the .json invocation on res inside the URL-producing method. The strong implication from the rest of the code is that the aim is to return (to the client) the result of the unityMartMediaCollection
call.