首页 > 解决方案 > 使用 Promise.all() 结果执行另一个查询的语法

问题描述

我有一个一个Promise.all()接一个地执行两个查询。在Promise.all()我想使用第二个查询的结果执行第三个查询的结果中。

我将如何创建一个function()我可以在里面干净地使用的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' });
    });
});

我想不通的是如何收听第三个查询的结果并返回一个return res.status(200).send({ success: true });

或错误。

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

function performThirdQuery(resultFromSecondQuery) {
        const updateDeviceIdEndpointArn = db.collection('deviceids')
            .updateOne(
                { device_id: deviceId },
                { $set: { device_endpoint_arn: deviceId } }
            );
    }

标签: node.jsexpresspromisepromise.all

解决方案


我有一个一个Promise.all()接一个地执行两个查询

那不是这样Promise.all做的。这两个操作并行运行,都在你得到upsertDeviceIdand时开始createEndpoint(这可能是你从其他地方得到的承诺),并Promise.all在履行其承诺之前等待它们都被履行(或等待其中一个在拒绝之前拒绝它承诺)。

但是假设您确实想并行运行它们,您通常做的是返回第三个查询的结果(在前两个查询完成之前不会运行):

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' });
    });
});

注意return之前的performThirdQuery. 假设performThirdQuery返回一个promise,这会将promise 从第一个履行处理程序解析为promise from performThirdQuery(当您将promise 解析另一个promise 时,它​​使前者的结果由后者的结果决定)。在另一种情况下(upsertDeviceIdResult.upsertedCount > 0不正确),处理程序只是隐式返回undefined。第二个履行处理程序在第一个处理程序的承诺被履行时运行,或者立即执行,undefined或者当upsertDeviceIdResult.upsertedCount > 0 真时,当该承诺被履行时。

在现代环境中(包括最近的 Node.js 版本),您可以使用async函数await来代替:

// (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' });
}

旁注——而不是:

    .then((values) => {

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

您可以在参数列表中使用解构:

    .then(([upsertDeviceIdResult, createEndpoint]) => {
        // ...

推荐阅读