node.jscloudinary

Cloudinary async wait upload for multiple images at once then save to array in node js


Hi I am look for a solution for API server side upload using Node Js asyc wait functionality for uploading multiple images then catch into an array. I follow this link to implement my code. In console it shows the array that I expect, but it does not give me any responses.

Here is what I tried so far,

exports.upload_image = async(req, res) =>{
  //let filePaths = req.files.path;

  let multipleUpload = new Promise(async (resolve, reject) => {
    let upload_len = req.files.length;
    let upload_res = new Array();

      for(let i = 0; i < upload_len; i++)
      {
          let filePath = req.files[i].path;
          await cloudinary.v2.uploader.upload(filePath, { use_filename: true, unique_filename: false }, function (error, result) {
              if(upload_res.length === upload_len)
              {
                /* resolve promise after upload is complete */
                resolve(upload_res)
              }
              else if(result)
              {
                /*push public_ids in an array */  
                upload_res.push(result.public_id);
              } else if(error) {
                console.log(error)
                reject(error)
              }

          })

      } 
  })
  .then((result) => result)
  .catch((error) => error)

  let upload = await multipleUpload;
  res.json({'response':upload})
}

Any suggestion would be appreciated. Thanks.


Solution

  • I would take a different approach here. You are mixing up promises and async/await in a way that is pretty hard to read and debug.

    I would do this instead: Map your files to an array of promises and then call Promise.all():

    exports.upload_image = async(req, res) =>{
        // res_promises will be an array of promises
        let res_promises = req.files.map(file => new Promise((resolve, reject) => {
            cloudinary.v2.uploader.upload(file.path, { use_filename: true, unique_filename: false }, function (error, result) {
                if(error) reject(error)
                else resolve(result.public_id)
            })
        })
        )
        // Promise.all will fire when all promises are resolved 
        Promise.all(res_promises)
        .then(result =>  res.json({'response':upload}))
        .catch((error) => {/*  handle error */ })
    }
    

    Here's a snippet with a fake upload function and a list of 'files':

    function upload(file, fn) {
      // fake upload file, just return file as id
      setTimeout(() => fn(null, {
        public_id: file
      }), Math.floor(Math.random() * 500))
    }
    
    // fake req.files
    let files = [1, 2, 3, 4, 5, 6]
    
    let upload_image = () => {
      let upload_res = files.map(file => new Promise((resolve, reject) => {
        upload(file, (error, result) => {
          if (error) reject(error)
          else resolve(result.public_id);
        })
      }))
    
      Promise.all(upload_res)
        .then(result => console.log({
          'response': result
        }))
        .catch(error => error)
    
    }
    upload_image()