Search code examples
javascriptpromisebluebird

How can I wait for all promises to resolve before returning all their values?


I'm using Promise.map from bluebird. I'm trying to wait for all promises to resolve before dispatching an event that contains an array of objects.

readFiles() {
    const fileArray = Array.from(this.fileSelectInput.files)
    const promises = []

    window.Promise.map(fileArray, (file, index) => {
      return window.jsmediatags.read(file, {
        onSuccess: tag => {
          promises.push({
            id: index + 1,
            title: tag.tags.title || undefined,
            artist: tag.tags.artist || undefined
          })
          promises.sort((a, b) => a.id - b.id)
          console.log('I should be first')
        }
      })
    }).then(() => {
        console.log('I should be second')
        this.dispatchEvent(new CustomEvent('tracks-selected', {
          detail: promises
        }))
      }
    }

I'm running into the problem where I should be second is printed to the console before I should be first. the detail: promises dispatched by the event contains an empty array.


Solution

  • You're probably looking for

    const fileArray = Array.from(this.fileSelectInput.files);
    
    window.Promise.map(fileArray, file => {
      return new Promise((resolve, reject) => {
        window.jsmediatags.read(file, {
          onSuccess: resolve,
          // also pass reject as an error handler if jsmediatags supports that
        });
      });
    }).then(tags => {
      const results = tags.map(tag => ({
        id: index + 1,
        title: tag.tags.title || undefined,
        artist: tag.tags.artist || undefined
      }));
      // results.sort((a, b) => a.id - b.id) - not necessary given .map() keeps the order
      this.dispatchEvent(new CustomEvent('tracks-selected', {
        detail: results
      }))
    });