简体   繁体   English

Node.js 事件循环忽略读取流数据事件中的 setTimeout?

[英]Node.js event loop ignores setTimeout inside read stream data events?

I am clarifying a doubt that I have regarding how Node.js executes timers.我澄清了我对 Node.js 如何执行计时器的疑问。 Normally when having a setTimeout block in your node script, the event loop, even if does not have anything else will wait for specified milliseconds in setTimeout and exits once it has run the callback.通常,当您的节点脚本中有 setTimeout 块时,事件循环,即使没有其他任何东西,也会在 setTimeout 中等待指定的毫秒数,并在运行回调后退出。

But consider below code但考虑下面的代码

const fs = require('fs');

let readable = fs.createReadStream('large.csv');
readable.on('data', async chunk => {
    let rows = parseCsvRow(chunk);  
    try {
        for (let i = 0; i < rows.length; i++) {
            console.log(i);
            await someAsyncOperation(rows[i]);
        }
    } catch (error) {
        //something went wrong
    }
});

readable.on('end', chunk => {
    console.log('csv file processed successfully');
});

function someAsyncOperation(){
    return new Promise((resolve, reject) => {
        setTimeout(resolve, 2000);
    });
}

The csv file I am reading has about 300 rows and I am firing an ajax request for each(code hidden for simplicity) which takes about 100ms to run and i have simulated it here using a setTimeout.我正在阅读的 csv 文件有大约 300 行,我正在为每个(为简单起见隐藏代码)发出一个 ajax 请求,运行大约需要 100 毫秒,我在这里使用 setTimeout 模拟了它。

When I run above program it exits almost instantly without waiting for all pending setTimeout timers to run successfully.当我在上面运行程序时,它几乎立即退出,而无需等待所有挂起的 setTimeout 计时器成功运行。 Just because the timers where scheduled from inside a data event on read stream does event loop ignore it ?仅仅因为从读取流上的data事件内部调度的计时器是否会忽略它? Should not it wait for all timers to execute ?它不应该等待所有计时器执行吗?

Note - I understand that above code is not the right way to do what I am doing but this is just a sample to demonstrate the concept that I am having a hard time understanding.注意 - 我知道上面的代码不是做我正在做的事情的正确方法,但这只是一个示例,用于演示我很难理解的概念。

This has nothing to do with Node.js, or the event loop.这与 Node.js 或事件循环无关。

The problem is that you're passing an async function into something that won't do anything with the promise it returns.问题是你将一个async函数传递给它返回的承诺不会做任何事情的东西。 That's one of the promise antipatterns.这是承诺的反模式之一。 Only use async functions as callbacks when one of these is true:仅当以下之一为真时才使用async函数作为回调:

  • The thing executing the callback will use or return the promise (for instance, Promise.all because it uses them, or map on arrays because it returns them)执行回调的事物将使用或返回承诺(例如, Promise.all因为它使用它们,或者map到数组因为它返回它们)
  • You don't care if the thing calling your async function continues working while your async function may be paused on an await , and you wrap everything in the async function in a try / catch that handles rejections.您不在乎调用您的async函数的东西是否继续工作,而您的async函数可能在await上暂停,并且您将async函数中的所有内容都包装在处理拒绝的try / catch中。

The Node.js specific part is: If you want to prevent further calls to your data handler until you've finished doing something, you need to pause the stream and thenresume it later. Node.js 特定部分是:如果您想在完成某件事之前阻止进一步调用您的data处理程序,您需要pause流,然后再resume它。

As it is in most cases, my confusion was because of a typo in my sample code.在大多数情况下,我的困惑是因为我的示例代码中有一个错字。

It was a typo in my code due to which there was an uncaught error in someAsyncFunction .这是我的代码中的一个错字,因为someAsyncFunction有一个未捕获的错误。 This uncaught error made node to exit the program.这个未捕获的错误使节点退出程序。 I have fixed it and now it works as expected.我已经修复了它,现在它按预期工作。 The current code as in shown in the question description correctly waits for timers to be executed before node exits the process.问题描述中显示的当前代码在节点退出进程之前正确等待计时器执行。

TL;DR - Node will wait for all timers to be executed before exiting the process. TL;DR -节点将在退出进程之前等待所有计时器执行完毕。 It does not matter if the timers are set from events callbacks or any other place for that matter(also you should not be having any uncaught errors)计时器是从事件回调或任何其他地方设置的都没有关系(你也不应该有任何未捕获的错误)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM