Search code examples
javascriptnode.jspromise

await does not suspend the execution till it finishes


for the below posted code, despite i am using await before Promise.all, the execution of the code does not wait till await Promise.all finishes first. what happens is, the code that contains:

.then(async () => {
        let averagesNDVIs = null;
        let sorted = null;
        let minMaxNDVI = null;
        ......
        ......
        ......

is always gets executed first.

please let me know why that is happening and how to solve this issue

code

.then(async (resp) => {
    bandsDataForTS1 = resp[0];
    bandsDataForTS2 = resp[1];

    await Promise.all([
        ...bandsDataForTS1.map((data, index) => {
            IOUtils.writeForPath(
                titlesOfBandsAsGeoTIFFForTS1[index],
                IOResources.CONST_OUTPUT_PATH_FOR_TIFFS.description,
                data.contents,
                '.tiff',
            )
            .then(ioResults => {
                processAPIBandsAsGeoTIFFFileNamesForTS1.push(ioResults.fileName);
                processAPIBandsAsGeoTIFFFullPathsForTS1.push(ioResults.fullPath);
                this.#msg = ({msg:infoTag + 'WS:/*************************************++WSSentinelhubProcessAPINDVIsProcessor/ tiff-contents are written to file successfully.', 
                    processAPIPathOfBandsDataAsGeoTIFFFForTS1: ioResults.fullPath,
                    processAPIFileNameOFBandsDataAsGeoTIFFForTS1: ioResults.fileName,
                });
                console.info(this.#msg);
            })
            .catch(e => {
                this.#msg = ({msg:infoTag + 'WS:/WSSentinelhubProcessAPINDVIsProcessor/ tiff-contents failed to be written to file.', 
                    processAPIPathOfBandsDataAsGeoTIFFFForTS1: ioResults.fullPath,
                    processAPIFileNameOFBandsDataAsGeoTIFFForTS1: ioResults.fileName,
                });
                console.info(this.#msg);
                throw new Error(this.#msg);
            });
        }),
        
        ...bandsDataForTS2.map((data, index) => {
            IOUtils.writeForPath(
                titlesOfBandsAsGeoTIFFForTS2[index],
                IOResources.CONST_OUTPUT_PATH_FOR_TIFFS.description,
                data.contents,
                '.tiff',
            )
            .then(ioResults => {
                processAPIBandsAsGeoTIFFFileNamesForTS2.push(ioResults.fileName);
                processAPIBandsAsGeoTIFFFullPathsForTS2.push(ioResults.fullPath);
                this.#msg = ({msg:infoTag + 'WS:/WSSentinelhubProcessAPINDVIsProcessor/ tiff-contents are written to file successfully.', 
                    processAPIPathOfBandsDataAsGeoTIFFFForTS2: ioResults.fullPath,
                    processAPIFileNameOFBandsDataAsGeoTIFFForTS2: ioResults.fileName,
                });
                console.info(this.#msg);
            })
            .catch(e => {
                this.#msg = ({msg:infoTag + 'WS:/WSSentinelhubProcessAPINDVIsProcessor/ tiff-contents failed to be written to file.', 
                    processAPIPathOfBandsDataAsGeoTIFFFForTS2: ioResults.fullPath,
                    processAPIFileNameOFBandsDataAsGeoTIFFForTS2: ioResults.fileName,
                });
                console.info(this.#msg);
                throw new Error(this.#msg);
            });
        }),
    ])
    .then(async () => {
        let averagesNDVIs = null;
        let sorted = null;
        let minMaxNDVI = null;
        //to note/comment: the element of index [0] is the one of interest, as it contains the averages vlaues of ndvis. The bands are in this order:[averages, numOfCloudFreeSamples, numOfCloudySamples, percentageOfCloudFree, percentageOfCloudy];
        averagesNDVIs = bandsDataForTS1[0].contents;
        sorted = averagesNDVIs.sort((a, b) => a-b);
        minMaxNDVI = MathUtils.findMinMax('_NDVI_averages_GeoTIFF_TS1_', averagesNDVIs);
        percentile10ForTS1 = MathUtils.findPercentile('_NDVI_averages_GeoTIFF_TS1_', sorted, .1).percentile;
        percentile90ForTS1 = MathUtils.findPercentile('_NDVI_averages_GeoTIFF_TS1_', sorted, .9).percentile;
        minNDVIForTS1 = minMaxNDVI.min;
        maxNDVIForTS1 = minMaxNDVI.max;

        //to note/comment: the element of index [0] is the one of interest, as it contains the averages vlaues of ndvis. The bands are in this order:[averages, numOfCloudFreeSamples, numOfCloudySamples, percentageOfCloudFree, percentageOfCloudy];
        averagesNDVIs = bandsDataForTS2[0].contents;
        sorted = averagesNDVIs.sort((a, b) => a-b);
        minMaxNDVI = MathUtils.findMinMax('_NDVI_averages_GeoTIFF_TS2_', averagesNDVIs);
        percentile10ForTS2 = MathUtils.findPercentile('_NDVI_averages_GeoTIFF_TS2_', sorted, .1);
        percentile90ForTS2 = MathUtils.findPercentile('_NDVI_averages_GeoTIFF_TS2_', sorted, .9);
        minNDVIForTS2 = minMaxNDVI.min;
        maxNDVIForTS2 = minMaxNDVI.max;
    });                            
})

Solution

  • Your map callbacks are not retuning anything:

    await Promise.all([
        ...bandsDataForTS1.map((data, index) => {
            // you are not returning anything here!
            // it should be return IOUtils.writeForPath(...)
            IOUtils.writeForPath(
                titlesOfBandsAsGeoTIFFForTS1[index],
                IOResources.CONST_OUTPUT_PATH_FOR_TIFFS.description,
                data.contents,
                ".tiff"
            )
                .then((ioResults) => { ... })
                .catch((e) => { ... });
        }),
        ...
    ]);
    

    Same for the second array.

    Quick solution: return from the callback.

    More robust solution: refactor your code to use more functions and replace the .then() instances with async/await.