Search code examples
javascriptpromisees6-promise

How to make status update with Promises in Javascript?


I have a function that returns a Promise:

export const uploadImages = (images, callbackProgress) =>{
  return new Promise((resolve, reject) =>{...}

Somewhere in there the function is resolved and I call the 'resolve()' method to return the result. This works as expected.

I want to report the upload progress so I tried to use a callback. This doesn't work cause the arguments passed to the callback are undefined in the receiving end. I haven't understood the real reason because the arguments are well defined just before the callback is invoked.

Anyway as a workaround does the Promise object have 'onProgressChange' method in addition to the 'resolve' and 'reject' that I could use?

Here is the function invocation:

uploadImages(fileList, function(progress, id) {
        console.log("SCENE1 | uploadImages() | progress...")
        console.log("SCENE1 | uploadImages() | id: ", id)
        console.log("SCENE1 | uploadImages() | progress: ", progress)
      }).then(response => {
        console.log("SCENE1 | uploadImages() | done, response: ", response)
      }, error => {
        console.log("SCENE1 | uploadImages() | error!")
      })

Here every time the 'progress' variable is undefined even though it is defined in the uploadImages function itself.

EDIT

Here is the full function that invokes the callback.

The variables 'id' and 'percentage' are defined but after they go into callback only ID comes out as defined while percentage is undefined. The fact that one of them is only undefined boggles my mind.

export const uploadImages = (images, callbackProgress) =>{
 return new Promise((resolve, reject) =>{

  const myUploadProgress = (thumbId) => (progress) => {
    let id = thumbId
    let percentage = Math.floor((progress.loaded * 100) / progress.total)
    console.log("FUNCATION | uploadImages | calling back with id: ", id)
    console.log("FUNCATION | uploadImages | calling back with progress: ", percentage)
    callbackProgress.call(percentage, id)
  }
  var originals = []
  var thumbnails = []
  let totalNrOfImages = images.length
  var uploadImageCounter = 0
  var i;
  for (i = 0; i < images.length; i++) {
    var thumbId = i
    var config = {
      onUploadProgress: myUploadProgress(thumbId)
    };
    const formData = new FormData()
    formData.append('img', images[i])
    uploadImage2(formData, config).then(resp => {
      originals.push(resp.oriUrl)
      thumbnails.push(resp.thumbUrl)
      uploadImageCounter=uploadImageCounter+1
      if(images.length == uploadImageCounter){
        resolve({orig:originals, thumbs:thumbnails});
      }
    })
  }
 })
}

Solution

  • Since your uploadImagesexpects 2 arguments and you pass only one here:

    const myUploadProgress = (thumbId) => (progress) => {
        let id = thumbId
        let percentage = Math.floor((progress.loaded * 100) / progress.total)
        console.log("FUNCATION | uploadImages | calling back with id: ", id)
        console.log("FUNCATION | uploadImages | calling back with progress: ", percentage)
        callbackProgress.call(percentage, id) // here
      }
    

    Because callbackProgress is invoked with context percentage and with argument id, which is evidently not what you want. More info here.

    The call() method calls a function with a given this value and arguments provided individually.

    So change it to:

    const myUploadProgress = (thumbId) => (progress) => {
        let id = thumbId
        let percentage = Math.floor((progress.loaded * 100) / progress.total)
        console.log("FUNCATION | uploadImages | calling back with id: ", id)
        console.log("FUNCATION | uploadImages | calling back with progress: ", percentage)
        callbackProgress.call(null, percentage, id)
      }
    

    By passing null you provide the context, which will default to global scope, but in your callback you don't care since you are not using this keyword in any way.

    Edit:

    Or (thanks for reminding to Bergi just use callbackProgress(percentage, id).