0

I have an array called imagesToUpload. Uploading function returns a promise. Right now I have to wait, images upload by one after another. This is my sample code.

function uploadTos3Bucket(filename){
    return new Promise((resolve,reject)=>{
        resolve(filename+'.png')
    })
}

const imagesToUpload = ['Homer','Bart','Lisa','Millhouse'];

async function controller() {
    const links = []

    for (const imageFile of imagesToUpload) {
        const link = await uploadTos3Bucket(imageFile);
        links.push(link)
    }
    console.log('links',links)
    
}
controller();

Instead of this I want something where I pass the images array. Images upload parallel. Once all finished I get the links array. Of-cause I know the concept of Promise.all()

This is not what I want.

const [image1,image2] = await Promise.all([uploadTos3Bucket('Homer'),uploadTos3Bucket('Bart')])

I don't want assign to so many variables. I just want an array with all the links and most importantly if some image failed to upload, it should ignore and not break the entire process.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
margherita pizza
  • 6,623
  • 23
  • 84
  • 152

1 Answers1

4

From the imagesToUpload array, use .map to transform it into an array of Promises, then call Promise.allSettled on that array, filter for only the fulfilled promises by checking the status property of each resulting object, and finally .map to their resolve values:

function uploadTos3Bucket(filename){
    return new Promise((resolve,reject)=>{
        resolve(filename+'.png')
    })
}

const imagesToUpload = ['Homer','Bart','Lisa','Millhouse'];

async function controller() {
  const results = await Promise.allSettled(imagesToUpload.map(uploadTos3Bucket));
  const links = results
    .filter(({ status }) => status === 'fulfilled')
    .map(({ value }) => value);
  console.log('links',links)  
}
controller();

For browsers that don't recognize Promise.allSettled yet, add a polyfill, or implement the functionality with one of the many methods listed here.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • A standard `Promise` no longer exposes a `status` property. – Alnitak Jan 20 '20 at 10:49
  • No, but `Promise.allSettled` resolves to an array of objects which *do* have that property - press "Run code snippet" (on Chrome, FF, Safari, or Node) to see it working – CertainPerformance Jan 20 '20 at 10:50
  • oops, yes - I hadn't noticed your use of `allSettled`. – Alnitak Jan 20 '20 at 10:52
  • @CertainPerformance this works! Thanks a lot. But will this improve the performance level. I tried this with my old one using console.timeEnd() seems this new one take more time? – margherita pizza Jan 20 '20 at 11:06
  • @PathumKalhan It shouldn't - this will run in parallel. In contrast, your original code `await`s each Promise in serial, which should take *much* longer than the parallel method – CertainPerformance Jan 20 '20 at 11:07
  • @CertainPerformance I didn't check it with the actual s3upload function. May be this will work with that. Anyways Thanks a lot. =) – margherita pizza Jan 20 '20 at 11:10