node.js - 在循环中使用异步操作超时
问题描述
问题:我有一个要删除的用户列表。不仅用户本人被删除,而且与他相关的大量数据也被删除。一些涉及删除用户信息的表包含数百万条记录。所有内部进程在删除时都是异步启动的。如果删除一个用户时没有问题,并且后台所有进程都成功(即客户端不期望响应),那么如果您运行其中几个,这会占用所有服务器资源,这只要它被移除,自然会对网站的工作产生负面影响。
for (let i = 0; i < users.length; i++) {
const user = users[i];
await this.removeInstance(user, removedBy);
}
this.removeInstance包含许多其他异步操作。
我想要的:每隔 3 分钟启动一个异步操作this.removeInstance 。数据删除的速度对我来说并不重要,但根据我的观察,1-2 分钟就足以“完全完成”一个用户。
注意: this.removeInstance 返回已删除的用户,但我不能使用它,因为已经有十几个进程在后台运行以清除他的信息。
谢谢你的帮助!
解决方案
您可以创建一个包装函数,将异步任务的完成延迟到最低限度:
const wait = ms =>
new Promise(resolve => setTimeout(resolve, ms));
const delayCompletion = minTime => task =>
Promise.allSettled([task(), wait(minTime)])
.then(([result]) => result.status === "fulfilled"
? result.value
: Promise.reject(result.reason)
);
例子:
const wait = ms =>
new Promise(resolve => setTimeout(resolve, ms));
const delayCompletion = minTime => task =>
Promise.allSettled([task(), wait(minTime)])
.then(([result]) => result.status === "fulfilled"
? result.value
: Promise.reject(result.reason)
);
//showcase:
async function main() {
console.log("-- start loop --");
for(let i = 0; i < 3; i++) {
console.log(`start iteration ${i}`);
const delayAtLeastTwoSeconds = delayCompletion(2000);
const oneSecondtask = () => wait(1000);
await delayAtLeastTwoSeconds(oneSecondtask);
console.log(`finish iteration ${i}`);
}
console.log("-- finish loop --");
}
main();
Promise.allSettled()
等到所有的 Promise 都不再挂起。我们给它一个异步任务,它会添加另一个以最小延迟,所以如果task
提前完成,那么它仍然必须等到延迟计时器完成。相反,如果延迟计时器首先完成但task
尚未完成,则仍将等待。
Promise.allSettled
解析为一组承诺,其中每个承诺都有一个状态"fulfilled"
或"rejected"
。我们只对数组的第一项感兴趣,因为它是task
- 第二项是延迟。如果成功,我们只返回它的值,如果不成功,则使用原始拒绝原因拒绝。这种方式delayCompletion
仍然保留与原始承诺相同的语义,并且任何使用原始承诺的代码都可以透明地使用来自delayCompletion
.
在某些方面,这与Promise.race()
首先解决的承诺相反。相反,我们等待最后一个,但我们确实有一个固定的返回值。
使用此辅助函数,您的代码可以像这样转换:
const safeDelay = delayCompletion(3 * 60 * 1000); //3 minutes
for (let i = 0; i < users.length; i++) {
const user = users[i];
await safeDelay(() => this.removeInstance(user, removedBy));
}
推荐阅读
- javascript - 页面加载时图像显示不成比例
- javascript - setInterval 函数 JavaScript 的问题
- xml - 无法解析 XML 以获取 VBA 中的特定信息
- xamarin.android - UI测试xamarin android上的黑屏谷歌地图
- c++ - 我应该使用多个角色还是一个将实际属性推迟到 QObject 包装/公开数据作为其属性
- python - 如何将欧几里德距离函数应用于熊猫数据框中的 groupby 对象?
- javascript - undefined 不是对象(评估 '_this.props.navigation.navigate')
- scala - 是否有只有语法的 Scala 版本(没有 Predef 等)
- swift - 无法在我的扩展中创建/发送 iMessage 在除初始视图之外的任何视图中
- node.js - node JS:从同步方法调用异步方法