1

I have a Promise.all() that performs two queries one after the other. In the result of the Promise.all() I want to perform a third query using the result from the second query.

How would I create a function() that I can cleanly use inside the Promise()?

Promise
    .all([upsertDeviceId, createEndpoint])
    .then((values) => {

        const upsertDeviceIdResult = values[0];
        const createEndpoint       = values[1];

        if(upsertDeviceIdResult.upsertedCount > 0){
            //Perform third query here
            //performThirdQuery(createEndpoint.EndpointArn);
        }
        
        return res.status(200).send({ success: true });

    })
    .catch((err) => {
        console.log(err);
        return res.status(400).send({ reason: 'unknown' });
    });
});

What I can't figure out is how can I listen to the results of this third query and return a return res.status(200).send({ success: true });

or an err.

return res.status(500).send({ success: false});

function performThirdQuery(resultFromSecondQuery) {
        const updateDeviceIdEndpointArn = db.collection('deviceids')
            .updateOne(
                { device_id: deviceId },
                { $set: { device_endpoint_arn: deviceId } }
            );
    }
DIRTY DAVE
  • 2,523
  • 2
  • 20
  • 83

1 Answers1

2

I have a Promise.all() that performs two queries one after the other

That isn't what Promise.all does. Both operations run in parallel, both having been started when you got upsertDeviceId and createEndpoint (which are presumably promises you got from somewhere else), and Promise.all waits for them both to be fulfilled before fulfilling its promise (or waits for one of them to reject before rejecting its promise).

But assuming that you did want to run them in parallel, what you usually do is return the result of the third query (which won't run until both of the previous ones complete):

Promise
    .all([upsertDeviceId, createEndpoint])
    .then((values) => {

        const upsertDeviceIdResult = values[0];
        const createEndpoint       = values[1];

        if(upsertDeviceIdResult.upsertedCount > 0){
            return performThirdQuery(createEndpoint.EndpointArn);
        }
    })
    .then(() => {
        res.status(200).send({ success: true });
    })
    .catch((err) => {
        console.log(err);
        res.status(400).send({ reason: 'unknown' });
    });
});

Note the return before performThirdQuery. Assuming performThirdQuery returns a promise, this resolves the promise from that first fulfillment handler to the promise from performThirdQuery (when you resolve a promise to another promise, it makes the former's result determined by the latter's result). In the other case (upsertDeviceIdResult.upsertedCount > 0 isn't true), the handler just implicitly returns undefined. The second fulfillment handler runs when the promise from the first handler is fulfilled, either immediately with undefined or, when upsertDeviceIdResult.upsertedCount > 0 is true, when that promise is fulfilled.

In modern environments (including any vaguely recent version of Node.js), you can use an async function and await instead:

// (In an `async` function)
const [upsertDeviceIdResult, createEndpoint] = await Promise.all([upsertDeviceId, createEndpoint]);
try {
    if (upsertDeviceIdResult.upsertedCount > 0) {
        await performThirdQuery(createEndpoint.EndpointArn);
    }
    res.status(200).send({ success: true });
} catch (err) {
    console.log(err);
    res.status(400).send({ reason: 'unknown' });
}

Side note — Instead of:

    .then((values) => {

        const upsertDeviceIdResult = values[0];
        const createEndpoint       = values[1];
        // ...

you can use destructuring in the parameter list:

    .then(([upsertDeviceIdResult, createEndpoint]) => {
        // ...
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875