1

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.

5
  • you are not calling the function await multipleUpload(); Commented Jun 24, 2018 at 23:36
  • Thanks for the quick responce, Still not working. it give me an error saying "multipleUpload is not a function" Commented Jun 24, 2018 at 23:45
  • You are awaiting cloudinary.v2.uploader.upload, but I don't that returns a promise. Commented Jun 24, 2018 at 23:45
  • 1
    await only works on functions that return a promise, not functions that just take an ordinary callback. You will have to "promisify" that function (convert callback to a promise) to use it with await. Commented Jun 24, 2018 at 23:50
  • in this if(upload_res.length === upload_len) line of code I modified as if(upload_res.length == req.files.length-1) then it gave me the response, but it is only having details for two images while I send three images on postman. Here is the response { "response": [ "1529884523808bebbb1d5ff29328157080e4e2e5d15a29c5aa34a", "1529884523809d2bf46fbe4c12e06481303d85f49f125e18fbd39" ] } Commented Jun 25, 2018 at 0:01

2 Answers 2

8

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()

Sign up to request clarification or add additional context in comments.

1 Comment

This answer helped me in uploading multiple images at once. Thanks!
0

Using async-await within try-catch
This is an addition to Mark's answer, but with using await within try-catch instead of using then.

The code also returns the secure_url of the uploaded file instead of the public_id.

Note: If you are using an error handling middleware, there is no need for the try-catch wrapper.

exports.upload_image = async(req, res) =>{
try{
    // res_promises will be an array of promises
    let res_promises = await 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.secure_url)
        })
    })
    )
    // Promise.all will fire when all promises are resolved 
    let urlArray = await Promise.all(res_promises)

     res.json({'response': urlArray}))
} catch (error) {
    console.log('error: ', error);
  }
    
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.