alex
alex

Reputation: 7601

What can I do to make the following `.then()` to only trigger once?

In the following code. I'm running a loop for the properties of formFields. As you can see, I'm using a counter to only run this.updatePanoCollection() when all the files have been uploaded with api.uploadFieldFile:

  // formFields = { logo: { file: ... }, thumbnail: { file: ... } }

  let toUploadCount = 0
  let uploadedCount = 0

  Object.entries(formFields).forEach(([key, upload]) => {
    if (!upload || !upload.file) return
    toUploadCount++
    api.uploadFieldFile('logo', upload.file).then(downloadUrl => {
      formFields[key] = downloadUrl
      const updatePayload = {
        id: this.currentPanoCollection.id,
        data: formFields
      }
      uploadedCount++
      if (toUploadCount === uploadedCount) {
        // This only runs once right now
        return this.updatePanoCollection(updatePayload)
      }
    }).then(() => {
      // But this runs twice. It should only run once.
    }).catch(err => this.handleError(err))
  })

Now the problem is that the code inside .then() runs twice.

How to change this code so it only runs once (after all the files have been uploaded)?

Upvotes: 1

Views: 43

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371069

Use Promise.all rather than having to maintain a count of completes, like this:

Promise.all(
  Object.entries(formFields).map(([key, upload]) => {
    if (!upload || !upload.file) return;
    return api.uploadFieldFile('logo', upload.file)
      .then(downloadUrl => {
      formFields[key] = downloadUrl
    })
  })
)
  .then(() => {
    // all have been uploaded
    const updatePayload = {
      id: this.currentPanoCollection.id,
      data: formFields
    }
    return this.updatePanoCollection(updatePayload);
  })
  .then(() => {
    // update is completed as well
  })
  .catch(err => this.handleError(err))

Upvotes: 2

Related Questions