我如何处理延迟的承诺决议?
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);
}
我的代码处理了各种场景,而且很长,所以我在下面使用简化的伪代码进行了复制:
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);
}