Stop awaiting remaining promises if one returns sentinel value

Tags: ,



I have a function validateTables() that validates that data exists in several tables using a call (per table) to an async helper function queryTable() that queries the api. To pass validation, data must exist in every table. If a table is empty, the helper function will return false. I currently have the set of calls in a Promise.all() that checks the resulting array for any false values. For performance, I would rather stop awaiting the resolution of any remaining promises if and when a promise resolves to false. Promise.race() and .all() don’t work because they are concerned with when or if a promise resolves, not the returned value. Can I do this without losing the parallel processing of the async functions?

Generalized functions:

async queryTable(query, params) {
        try {
            returnData = []
            for await (const returnItem of api.executeQuery(query, params)){
                returnData.push(returnItem)
            }

            if (returnData.length > 0) {
                return true;
            }
            return false;
        }
        catch (err) {
            throw new Error(`${JSON.stringify(err)}`);
        }
    }

async validateTables() {
       const allDataExists = await Promise.all([
                this.queryTable(query, params),
                this.queryTable(query2, params2),
                this.queryTable(query3, params3),
                // and so on for several more
            ])
            if (!allDataExists.includes(false)) {
                return 'OK'
            }
            return 'Invalid'
    }

Answer

The promise returned by Promise.all will reject as soon as any of the containing promises reject. With that in mind, you could throw the sentinel value instead of returning it, and simply check for that in a try/catch around the await.

async queryTable(query, params) {
    try {
        returnData = []
        for await (const returnItem of api.executeQuery(query, params)){
            returnData.push(returnItem)
        }

        if (returnData.length > 0) {
            return true;
        }
        throw false;
    }
    catch (err) {
        throw new Error(`${JSON.stringify(err)}`);
    }
}

async validateTables() {
    try {
        const allDataExists = await Promise.all([
            this.queryTable(query, params),
            this.queryTable(query2, params2),
            this.queryTable(query3, params3),
            // and so on for several more
        ])
    } catch(e) {
        if(e instanceof Error) throw e
        return 'Invalid'
    }
    return 'OK'
}


Source: stackoverflow