Search code examples
javascriptpromisebluebirdvue.js

Promise.all() resolves immediately


I'm trying to take some action after upload completion of multiple images, using Promise.all.

However, the code after then runs before the code being dispatched.

What am I confusing here?

  submit_all_images({ dispatch, rootState }) {
    const imageFileArray = rootState.imageStore.imageFileArray 
    var promiseArray = []

    for ( var imageFile of imageFileArray ) {
      promiseArray.push(dispatch('get_signed_request', imageFile))
    }

    Promise.all(promiseArray)
      .then(results => {
        console.log("finished with results: " + results)
        return dispatch('submit_entire_form')
      });
  },
  get_signed_request ({ dispatch, commit, state }, imgFile) {
    const requestObject = {imageName: imgFile.name, imageType: `${imgFile.type}`}
    axios.post('http://localhost:3000/sign-s3', requestObject)
    .then(response => {
        if (response.body.signedRequest && response.body.awsImageUrl) {
          const signedRequest = response.body.signedRequest
          const awsImageUrl = response.body.awsImageUrl
          dispatch('upload_file', { imgFile, signedRequest, awsImageUrl })
        } else {
          alert('Could not get signed URL.');
        }
    }, error => {
      console.log("ERROR: " + error)
    })
  },

  upload_file ({ dispatch, commit, state}, { imgFile, signedRequest, awsImageUrl }) {
    axios.put(signedRequest, imgFile, {
      headers: {'Content-Type': imgFile.type}
    }).then(response => {
      console.log('finished uploading file: ' + imgFile.name )
      commit(types.UPDATE_LICENSE_IMG_URLS, awsImageUrl)
    }, error => {
      alert("fail")
      console.log(error)
    })
  },

Solution

  • I'm not entirely sure, since I have no experience with vuex, but I guess you're missing a few return statements.

    get_signed_request({ dispatch, commit, state }, imgFile){
        const requestObject = {imageName: imgFile.name, imageType: `${imgFile.type}`}
        //here
        return axios.post('http://localhost:3000/sign-s3', requestObject)
            .then(response => {
                if (response.body.signedRequest && response.body.awsImageUrl) {
                    const signedRequest = response.body.signedRequest
                    const awsImageUrl = response.body.awsImageUrl
                    //here
                    return dispatch('upload_file', { imgFile, signedRequest, awsImageUrl })
                } else {
                    alert('Could not get signed URL.');
                }
            }, error => {
                console.log("ERROR: " + error)
            })
    },
    
    upload_file({ dispatch, commit, state}, { imgFile, signedRequest, awsImageUrl }){
        //here
        return axios.put(signedRequest, imgFile, {
            headers: {'Content-Type': imgFile.type}
        }).then(response => {
            console.log('finished uploading file: ' + imgFile.name )
            //and here
            return commit(types.UPDATE_LICENSE_IMG_URLS, awsImageUrl)
        }, error => {
            alert("fail")
            console.log(error)
        })
    },
    

    So that get_signed_request returns a Promise that resolves only after axios.post().then() is done, wich depends on first resolving dispatch('upload_file', ...)

    And the same for upload_file depending on resolving axios.put().then()depending on commit(types.UPDATE_LICENSE_IMG_URLS, awsImageUrl)