[英]Break for event loop processing without breaking loop
I found myself trying to process a vast amount of data recently and I had to do some (lets call it) creative coding to get the desired result.我发现自己最近试图处理大量数据,我不得不做一些(让我们称之为)创造性的编码来获得所需的结果。
I knew the processing would be a multi day task so I wrote it in a way that could be interrupted and resumed.我知道处理将是一项多天的任务,所以我以一种可以中断和恢复的方式编写它。 But what stumped me was finding a nice way to process SIGINT/SIGTERM style events without wanting to break my loop.
但是让我难受的是找到了一种很好的方法来处理 SIGINT/SIGTERM 风格的事件,而不想打破我的循环。
btw these are obviously not the real names for my functions顺便说一句,这些显然不是我函数的真实名称
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);
I had failed to realise that SIGINT would never be processed while I was still in the for-loop and so would only ever finish after the entire dataset was processed (a very foolish oversight, I think I was deluded to believing it would work the same was as Arduino Hardware Interrupts. D'oh. Lesson learned.我没有意识到 SIGINT 在我还在 for 循环中时永远不会被处理,所以只有在整个数据集被处理后才会完成(一个非常愚蠢的疏忽,我想我被迷惑了相信它会工作相同就像 Arduino 硬件中断一样。天啊。吸取了教训。
Now that I realised this, my solution was to put half of my code at the end of the tick using the microtask async-await trick.现在我意识到了这一点,我的解决方案是使用微任务 async-await 技巧将我的一半代码放在滴答声的末尾。
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);
Now, this works as I expected and the await allows the loop to be paused and allow SIGINT/SIGTERM to be processed and then picks up if closed is set to true.现在,这按我的预期工作,等待允许循环暂停并允许处理 SIGINT/SIGTERM,然后在关闭设置为 true 时接收。 YAY.. But DAMN it looks nasty.
YAY .. 但该死的它看起来很糟糕。 I was hoping someone might have a better looking solution than this?
我希望有人可能有比这更好看的解决方案?
You will need to keep the flag, but you can make your main logic simpler.您将需要保留标志,但您可以使主要逻辑更简单。 Consider
考虑
let closed = false;
function* syncGenerator() {
yield* ~20-trillion-calculated-results;
}
function main( generator = syncGenerator() )
{
if (closed)
{
syncGracefulCleanup();
}
else
{
// assuming syncWork returns false when
// there are no more value
if ( syncWork( generator.next() ) )
{
// next-ish off to the event loop. this is NOT recursive,
// even though it may look a bit like it
setTimeout( () => main(generator), 0 );
}
}
}
process.on('SIGINT', () => close = true);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.