簡體   English   中英

Node.js 事件循環忽略讀取流數據事件中的 setTimeout?

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

我澄清了我對 Node.js 如何執行計時器的疑問。 通常,當您的節點腳本中有 setTimeout 塊時,事件循環,即使沒有其他任何東西,也會在 setTimeout 中等待指定的毫秒數,並在運行回調后退出。

但考慮下面的代碼

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);
    });
}

我正在閱讀的 csv 文件有大約 300 行,我正在為每個(為簡單起見隱藏代碼)發出一個 ajax 請求,運行大約需要 100 毫秒,我在這里使用 setTimeout 模擬了它。

當我在上面運行程序時,它幾乎立即退出,而無需等待所有掛起的 setTimeout 計時器成功運行。 僅僅因為從讀取流上的data事件內部調度的計時器是否會忽略它? 它不應該等待所有計時器執行嗎?

注意 - 我知道上面的代碼不是做我正在做的事情的正確方法,但這只是一個示例,用於演示我很難理解的概念。

這與 Node.js 或事件循環無關。

問題是你將一個async函數傳遞給它返回的承諾不會做任何事情的東西。 這是承諾的反模式之一。 僅當以下之一為真時才使用async函數作為回調:

  • 執行回調的事物將使用或返回承諾(例如, Promise.all因為它使用它們,或者map到數組因為它返回它們)
  • 您不在乎調用您的async函數的東西是否繼續工作,而您的async函數可能在await上暫停,並且您將async函數中的所有內容都包裝在處理拒絕的try / catch中。

Node.js 特定部分是:如果您想在完成某件事之前阻止進一步調用您的data處理程序,您需要pause流,然后再resume它。

在大多數情況下,我的困惑是因為我的示例代碼中有一個錯字。

這是我的代碼中的一個錯字,因為someAsyncFunction有一個未捕獲的錯誤。 這個未捕獲的錯誤使節點退出程序。 我已經修復了它,現在它按預期工作。 問題描述中顯示的當前代碼在節點退出進程之前正確等待計時器執行。

TL;DR -節點將在退出進程之前等待所有計時器執行完畢。 計時器是從事件回調或任何其他地方設置的都沒有關系(你也不應該有任何未捕獲的錯誤)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM