什么是构建我的控制流(承诺和循环)的明智方法?
What is a sensible way to structure my control flow (promises and looping)?
我不确定如何使用 promises/bluebird 充分实现我想要的控制流程。
基本上我有一个存储了 X 'tasks' 的数据库,每个数据库都需要按顺序加载和执行。我不想 运行 同时执行多个任务,整个代码必须无限期地继续执行。
到目前为止,我已经通过以下代码实现了这一点:
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 promises)在 运行ning 一段时间后可能会导致堆栈问题。
我想做的是将其重组为:
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());
非常感谢您的想法和建议!
什么堆栈问题?只要 getNextTaskRunner
是真正异步的(即它在某些时候将控制权交还给主循环,例如,如果它执行异步 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);
}
我不确定如何使用 promises/bluebird 充分实现我想要的控制流程。
基本上我有一个存储了 X 'tasks' 的数据库,每个数据库都需要按顺序加载和执行。我不想 运行 同时执行多个任务,整个代码必须无限期地继续执行。
到目前为止,我已经通过以下代码实现了这一点:
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 promises)在 运行ning 一段时间后可能会导致堆栈问题。
我想做的是将其重组为:
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());
非常感谢您的想法和建议!
什么堆栈问题?只要 getNextTaskRunner
是真正异步的(即它在某些时候将控制权交还给主循环,例如,如果它执行异步 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);
}