hypnagogia
hypnagogia

Reputation: 173

Using promises in React to wait for functions to finish within JavaScript map function

I've been trying to figure out what the proper way would be to write a promise for this function. I have an asynchronous function that makes an HTTP request to the server to retrieve a response, "documents_fileUploader." I am mapping through the "url" of each item within the response, and each url will go in to a function that makes another HTTP request and then sets the state. I want to fire the "upload()" function only after everything within the "documents_fileUploader()" function is complete. I tried doing this without a promise and it went straight to my "upload()" function because request was still pending. Any suggestions on how to go about this?

documents_fileUploader(formData).then(resp => {
  resp.data.items.map(url => {
    const key = url.split("/")[4];
    this.setState({
      urls: [...this.state.urls, url],
      keys: [...this.state.keys, key]
    });
    this.getFileObject(key);
  })
}).then(() => {
  this.upload();
})

getFileObject = file => {
  file_view(file).then(resp => {
    this.setState({
      mimeTypes: [...this.state.mimeTypes, resp.data.item.headers.contentType]
    })
  }).catch(err => {
    console.log(err);
  })
}

Upvotes: 0

Views: 346

Answers (1)

CRice
CRice

Reputation: 32176

  • To your main question, you can wait for every promise that your .map call returns by using the Promise.all method.
  • Second, in order for that to work, your getFileObject function must return the promise it creates.

So incorporating those two changes, your snippet might look like:

documents_fileUploader(formData).then(resp => {
  return Promise.all(resp.data.items.map(url => { // Wrap in Promise.all and return it
    const key = url.split("/")[4];
    this.setState({
      urls: [...this.state.urls, url],
      keys: [...this.state.keys, key]
    });
    return this.getFileObject(key); // Make sure to return this promise as well.
  }));
}).then(() => {
   // Now this won't happen until every `getFileObject` promise has resolved...
  this.upload();
})

getFileObject = file => {
  return file_view(file).then(resp => { // And return the promise here.
    this.setState({
      mimeTypes: [...this.state.mimeTypes, resp.data.item.headers.contentType]
    })
  }).catch(err => {
    console.log(err);
  })
}

Upvotes: 2

Related Questions