【发布时间】:2019-09-03 22:01:22
【问题描述】:
我发现自己最近试图处理大量数据,我不得不做一些(我们称之为)创造性编码来获得所需的结果。
我知道处理将是一个多天的任务,所以我以一种可以中断和恢复的方式编写它。但让我难过的是找到一种处理 SIGINT/SIGTERM 样式事件的好方法,而不想破坏我的循环。
顺便说一句这些显然不是我的函数的真实名称
let closed = false;
function* syncGenerator() {
yield* ~20-trillion-calculated-results;
}
function main() {
try {
for ( const value of syncGenerator() ) {
syncWork(value);
if (closed) {
syncGracefulCleanup();
break;
}
}
} catch ( err ) {
handleError(err);
} finally {
syncGracefulCleanup2();
}
}
process.on('SIGINT', () => closed = true);
我没有意识到当我还在 for 循环中时,SIGINT 永远不会被处理,因此只会在整个数据集被处理后才能完成(一个非常愚蠢的疏忽,我想我误以为它会工作与 Arduino 硬件中断相同。D'oh。经验教训。
现在我意识到了这一点,我的解决方案是使用微任务异步等待技巧将我的一半代码放在滴答声的末尾。
let closed = false;
function* syncGenerator() {
yield* ~20-trillion-calculated-results;
}
async function main() {
try {
for ( const value of syncGenerator() ) {
syncWork(value);
await new Promise(r => setImmediate(r)); // the new nasty
if (closed) {
syncGracefulCleanup();
break;
}
}
} catch ( err ) {
handleError(err);
} finally {
syncGracefulCleanup2();
}
}
process.on('SIGINT', () => closed = true);
现在,这可以按我的预期工作,并且 await 允许暂停循环并允许处理 SIGINT/SIGTERM,然后在 close 设置为 true 时继续。耶.. 但是该死的,它看起来很讨厌。 我希望有人可能有比这更好看的解决方案?
【问题讨论】:
-
您的
syncGenerator可以改为异步生成器吗? -
@noseratio 仅通过在该函数中移动 await setImmediate 代码。同样的问题,不同的位置。
-
我的意思是,当“~20-trillion-calculated-results”可用时,您真的能以自然的方式异步生成它们吗?并使用
for awaitloop消费? -
@noseratio 我刚刚为仅在生成器和 for-await-of 前面编写 async 的场景编写了一个快速测试。但可悲的是,它按我想象的方式工作。如果没有在异步生成器中放置实际的异步任务,它的工作方式与同步生成器完全一样,所以我必须将
await new Promise((r) => setImmidate(r));移到那里。正如我所说,同样的问题,只是位置不同。
标签: javascript node.js event-loop