0

How can i tell if the below code has finished for it to resolve the promise for the next task to happen

It currently downloads around ~500 files and saves them to disk, but how can i tell once the last file has been written to disk to resolve the promise?

exports.DownloadImages = function (provider, data) {
    return new Promise(function (resolve, reject) {

        data.forEach(function (vehicle) {
            var images = vehicle.Gallery;

            images.forEach(function (image) {

                const url = transformation.replaceAll(image, '[size]', 'original');
                const filename = transformation.replaceAll(transformation.ImageFilename(url), '[size]', 'original');
                const writer = fs.createWriteStream('./export/' + provider + '/' + filename);

                api.get(url, {
                    responseType: 'stream',
                    httpsAgent: new https.Agent({ keepAlive: true })
                }).then((response) => {
                    response.data.pipe(writer);
                })
                    .catch((error) => {
                        console.error('[HELPER] DownloadImages ' + error + ' on Image ' + url);
                    });
            });
        });
        // Need to check to see if all data has been processed...
        resolve();

    });

};
Tam2
  • 323
  • 1
  • 5
  • 16
  • Why not use [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) and [`map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)? – Sebastian Simon Oct 03 '19 at 17:12
  • How would i map a nested array, ultimately all i need is a list of URL's to download the images but my data structure is a top level array called data then within each element of that array there is a Gallery array which contains the image urls, so all the Gallery sub-arrays could be merged to produce one list of urls to then do a promise.all on? – Tam2 Oct 03 '19 at 17:37
  • @TamoorMalik Either that (flattening), or you call `Promise.all` on each of the inner mapped-to-promises arrays. – Bergi Oct 03 '19 at 17:38
  • @Bergi - I've re-written it like this (https://pastebin.com/HYdxYjPJ) - but the promise is still returned before the fs.createWriteStream has finished writing the files to disk – Tam2 Oct 03 '19 at 18:04
  • Problem A: you don't `return` or `await` the `api.get(…)` promise, so the promise that gets passed into `Promise.all` (the result of the callback function) resolves immediately. Problem B: you don't have [a promise that waits for the writing stream to finish](https://stackoverflow.com/a/39880990/1048572) – Bergi Oct 03 '19 at 18:09
  • Thanks, added `await new Promise(fulfill => stream.on("finish", fulfill));` to capture when it finishes writing and added a return to api.get and all seems to be working as expected – Tam2 Oct 03 '19 at 18:15

0 Answers0