我不确定如何使用promises / bluebird充分实现我想要的控制流程。
基本上我有一个存储了X'任务'的数据库,每个都需要按顺序加载和执行。我不希望同时运行多个任务,整个代码必须无限期地继续执行。
到目前为止,我已使用以下代码实现了此目的:
export default function syncLoop() {
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(syncLoop)
.catch((error) => {
throw new Error(error);
});
} else {
syncLoop();
}
});
}
getNextTaskRunner()只是从数据库中加载并解析下一个任务(根据时间戳计算)。或者它以null结算(没有任务可用)。
当完整任务完成时,taskRunner.startTask()将解析为null。
我被告知它的结构方式(递归/ w承诺)可能会在运行一段时间后导致堆栈问题。
我所想做的是将其重组为:
let running = false;
setInterval(() => {
if (!running) {
running = true;
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(() => {
running = false;
})
.catch((error) => {
log.error(error);
});
} else {
running = false;
}
});
}
}, 5000);
还是另一种可能性,使用某种形式的事件发射器?
task.on('complete', nextTask());
非常感谢您的意见和建议!
答案 0 :(得分:1)
什么堆栈问题?只要getNextTaskRunner
是真正的异步(即,它在某个时刻将控制权交还给主循环,例如,如果它执行async io),那么编写代码的方式就完全没问题了。在这种情况下,代码中没有递归。谁告诉你这是错误的。
虽然您可能希望在某处添加setTimeout
,但您不会在请求时充斥数据库。此外,如果getNextTaskRunner
不再同步(例如在内存缓存中),它会对您有所帮助:
export default function syncLoop() {
setTimeout(() => {
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(syncLoop)
.catch((error) => {
throw new Error(error);
});
} else {
syncLoop();
}
});
}, 2000);
}