Amiya Behera
Amiya Behera

Reputation: 2270

How to call a function after all async calls in loop are done?

The reader.onloadend calls a async function addData and reader.onloadend is in a loop.

const uploadFiles = () => {
    console.log(acceptedFiles)
    setLoading(true)
    console.log(loading)
    let i = 0
    let l = acceptedFiles.length

    for (i = 0; i < l; i++) {
      let file = acceptedFiles[i]
      const reader = new window.FileReader()
      reader.readAsArrayBuffer(file)
      reader.onloadend = () => {
        let buffer = Buffer(reader.result)
        console.log(buffer)
        addData(file.path, buffer)
      }
    }
  }

This is my async function addData

async function addData(name, buffer) {
    const file = await myfunction()
    
  }

I want to call setLoading(false) after all the async addData in the loop has been called. The onClick function doesn't work, loading is set to false when I click the button before all the async function is done.

const [loading, setLoading] = useState(false)
<button onClick={() => {
                uploadFiles()
                 setLoading(false) 
             }}
            disabled={loading}
          >

Upvotes: 4

Views: 538

Answers (1)

epascarello
epascarello

Reputation: 207501

Using promises you can know when all of the files have been read. Basic idea below

const uploadFiles = (evt) => {

  // set loading to true;

  const acceptedFiles = [...evt.target.files];

  // Create a map of promises that will resolve when file is read
  const readerPromises = acceptedFiles.map(file => {
    return new Promise(resolve => {
      const reader = new window.FileReader()
      reader.readAsArrayBuffer(file)
      reader.onloadend = () => {
        console.log(file);
        let buffer = reader; // Buffer(reader.result)
        resolve([file.name, buffer])
      }      
    });
  });

  // Detects when all of the promises are fully loaded
  Promise.all(readerPromises).then(results => {
    console.log(results);
    // set loading to false;
  });
  
};
<input type="file" multiple onchange="uploadFiles(event)" />

Upvotes: 5

Related Questions