Home > other >  Promise.all but in interval, how to achieve it?
Promise.all but in interval, how to achieve it?

Time:09-30

I want to upload 20 photos to imgur at once. But I want to do in certain time gap between each upload. I was using Promise.all([...listof20promises]). But now I want to do api calls in interval of 1 second, and also I should be able to get response in the form of .then((responseArray)=>...) like we get in Promise.all.

How can I achieve it?

CodePudding user response:

Use async/await and a normal loop with a delay between each iterations, for example:

const delay = t => new Promise(resolve => setTimeout(resolve, t));

const uploadAll = async files => {
  const results = [];

  for (const file in files) {
     if (results.length) {
        await delay(1000);  // 1 second
     }
     const response = await uploadFile(file);
     results.push({ file, response });
     
  }

  return results;
}

And use it as

uploadAll([ file1, file2, file3, ... ]).then(results => {

   // results[0] = { file, response }  where file === file1
   // results[1] = { file, response }  where file === file2
   // ...

});

CodePudding user response:

You can do as follows:

async function upload(files) {
  while (files.length) {
    await Promise.all(files.splice(0, 20));
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
}

upload([...]);

Remember that splice will mutate your array. If you don't want that, you can use slice like below:

async function upload(files) {
  let i = 0;
  while (i < files.length) {
    await Promise.all(files.slice(i, i  = 20));
    await new Promise(resolve => setTimeout(resolve, 1000));
  }
}

upload([...]);

CodePudding user response:

If you want the delay to be between one upload start to the next upload start, you can map the files, use a delay promise (taken from Yanick Rochon's answer) with the index of the current file * 1000 as the timeout, and then call the upload:

const delay = t => new Promise(resolve => setTimeout(resolve, t));

const uploadAll = files => Promise.all(
  files.map((file, i) =>
    delay(i * 1000).then(() => uploadFile(file))
  )
);

The main difference between Yanick Rochon's answer and mine, is that in his answer the next upload would start 1 second after the previous call ended, while this code would dispatch the calls within 1 second of each other, even if the previous call is still pending.

  • Related