我如何处理延迟的承诺决议?

How can I handle delayed promise resolution?

我的代码处理了各种场景,而且很长,所以我在下面使用简化的伪代码进行了复制:

const sendOrder = async function (Order) {
    return new Promise(async (resolve) => {
        console.log("order about to be place for " + Order.id + " at " + isoTime());

        try {
            const orderResponse = await sendOrderToBroker(Order);
            console.log("order " + Order.id + "sent to broker at " + isoTime());

            //Update db with details about successful order placement
            models.orders
                .update({
                    //Order status details
                })
                .then((countRowsUpdated) => {
                    console.log(
                        `Order ${orderId} success - ${countRowsUpdated} row(s) updated at time ${isoTime()}`
                    );
                    resolve(countRowsUpdated);
                });
        } catch (error) {
            //Update db with details about failed order placement
            models.orders
                .update({
                    //failed order status details
                })
                .then((countRowsUpdated) => {
                    console.log(
                        `Order ${orderId} failure - ${countRowsUpdated} row(s) updated at time ${new Date().toISOString()}`
                    );
                    resolve(countRowsUpdated);
                });
        }
    });
};

const run = async function () {
    const ordersToBeProcessed = [];
    const Order = {};

    const orders = await models.orders.findAll(); //database request via sequelize

    orders.map(async function (order) {
        if (order.action === "entry") {
            Order = populateOrderObject(order);
        }

        if (order.action === "exit") {

    try {
        currentPosition = await fetchCurrentPosition(); //network request via axios. Cause of the bug. Edited to include try... catch block
    Order = populateOrderObject(order, currentPosition);
} catch (error) {
//Update db with details about failed fetch position
            await models.orders
                .update({
                    //failed fetch position details including error
                })
    }
            
            
        }

        ordersToBeProcessed.push(sendOrder(Order));
    });

    Promise.allSettled(ordersToBeProcessed).then((responses) => {
        responses.map((response) => {
            console.log(" response: " + response.status + ", value: " + response.value);
        });
        console.log("processedOrders.length is: " + processedOrders.length);
        console.log("Number of responses is: " + responses.length);

        if (orders.length === responses.length) {
            setTimeout(run, 500);
        }
    });
};

setTimeout(run, 500);

这是下面的输出。作为参考,订单 361 和 362 是带有 order.action === "entry" 的入场订单,而订单 360 和 364 是退出订单:

Order engine started: 2020-10-12T21:22:47.712Z
running orders at time 2020-10-12T21:22:48.232Z
order about to be placed for 361 at time 2020-10-12T21:22:48.302Z
order about to be placed for 362 at time 2020-10-12T21:22:48.302Z
24
order about to be placed for 360 at time 2020-10-12T21:22:48.838Z
order about to be placed for 364 at time 2020-10-12T21:22:48.839Z
order 361 sent to broker at 2020-10-12T21:22:48.909Z
Order 361 success - 1 row(s) updated at time 2020-10-12T21:22:48.918Z
order 362 sent to broker at 2020-10-12T21:22:48.927Z
Order 362 success - 1 row(s) updated at time 2020-10-12T21:22:48.930Z
 response: fulfilled, value: 1
 response: fulfilled, value: 1
processedOrders.length is: 4
Number of responses is: 2
order 360 sent to broker at 2020-10-12T21:22:49.181Z
Order 360 success - 1 row(s) updated at time 2020-10-12T21:22:49.185Z
order 364 sent to broker at 2020-10-12T21:22:49.185Z
Order 364 success - 1 row(s) updated at time 2020-10-12T21:22:49.197Z

当 order.action 等于“退出”时,Promise.allSettled(以及 Promise.all)在没有这些退出命令的情况下解析。因此,响应中仅包含挂单。退出命令最终解决,但脚本终止,因为条件 setTimeout 永远不会被触发。我可以做些什么来实现在 Promise.allSettled.then 运行之前解决所有已处理订单的期望 objective?我如何处理退出订单中的额外网络请求,因为我认为这是问题的来源?我认为这与事件循环和微任务处理有关,但我无法从那里继续前进。

What can I do to achieve the desired objective of having all processed orders resolve before Promise.allSettled.then runs?

将它们放入 Promise.allSettled 正在等待的承诺数组中。您在 orders 上的循环有一个异步部分,并且退出命令放在 ordersToBeProcessed 数组 after 中,您在循环之后立即调用了 Promise.allSettled。使用 map 方法的正确写法是

async function run() {
    const orders = await models.orders.findAll(); //database request via sequelize

    const ordersToBeProcessed = orders.map(async function (order) {
//        ^^^^^^^^^^^^^^^^^^^^^^
        const Order = order.action === "entry" ? populateOrderObject(order) :
                      order.action === "exit" ? populateOrderObject(order, await fetchCurrentPosition()) :
                      undefined;
        return sendOrder(Order);^
//      ^^^^^^
    });

    const responses = await Promise.allSettled(ordersToBeProcessed);
    for (const response of responses) {
        console.log(" response: " + response.status + ", value: " + response.value);
    });
    console.log("All " + ordersToBeProcessed.length + "orders got processed");
    setTimeout(run, 500);
}