簡體   English   中英

Node.js fs.writeFile() 似乎不是異步的

[英]Node.js fs.writeFile() doesn't seem asynchronous

如果我們查看fs.writeFile()方法的 Node.js 文檔,我們會發現它本質上是異步的。

現在,考慮到這一點,我設置了以下代碼來測試這個想法:

const fs = require('fs');

function sync(delay) {
    const startingTime = new Date();
    while ((new Date() - startingTime) < delay) {
        // keep this loop going
    }
}


fs.writeFile(__dirname + '/hello.txt', 'Hello World', function() {});

sync(4000);

我在 VSCode 中打開了hello.txt文件,每當有數據寫入該文件時,VSCode 就會實時顯示。

我希望此代碼將Hello World寫入文件hello.txt ,在 4 秒之前(這是由sync(4000)引起的延遲),因為fs.writeFile()本質上是異步的(如文檔所述)。 然而,令我驚訝的是,任何數據都會在 4 秒寫入文件。

這似乎根本不是異步的!

我的問題是,為什么沒有在整個腳本同步執行之前將數據寫入文件hello.txt

我懷疑(順便說一句,我對操作系統線程了解不多)當fs.writeFile()時,它會在另一個空閑的操作系統線程上異步寫入文件(不阻塞主線程),但這不會似乎沒有發生。

我一直在測試很多與文件寫入實用程序相關的其他東西,例如可寫流,並且遇到了同樣的問題。 除非並直到所有同步執行完成,否則不會寫入任何內容。

我需要對這種內部事物有一個明確的解釋。

嘗試這個:

import { writeFile } from 'fs/promises'

function sync(delay) {
  const startingTime = new Date();
  while ((new Date() - startingTime) < delay) {
      // keep this loop going
  }
}

(async () => {
  await writeFile(__dirname + '/hello.txt', 'Hello World');

  sync(4000)
})();

盡管writeFile在行為上可能看起來是異步的,但 NodeJS 受到 JavaScript 是單線程語言這一事實的限制。 為了模擬異步,NodeJS 使用事件循環來處理操作。

我不確定writeFile function 的內部工作原理,但從代碼的運行方式來看,可以假設 3 個或更多任務被添加到事件循環中(一個用於創建文件,一個用於寫入創建的文件,一個用於處理回調)。 多個事件對於理解代碼執行方式的原因很重要。

writeFile function 調用執行時,'hello.txt' 文件生成為空(創建文件,第一個任務)。 但是,由於執行了writeFile調用,JavaScript 引擎已經繼續執行並執行了問題的罪魁禍首,您的sync function。 sync function 使用while循環來模擬延遲而不是通常使用的setTimeout function 是理解的關鍵內部發生了什么。

while 循環在這種情況下所做的是在寫入創建的文件之前劫持事件循環(這解釋了為什么創建文件但不寫入文件),因為while是一個阻塞操作。 您可以通過在sync function 之前使用writeFileSync添加另一個 I/O 操作來驗證此行為。將創建兩個文件,但只有writeFileSync函數的文件會寫入任何內容。

由於while循環阻塞了事件循環,數據在您的延遲后寫入文件,因為那是while循環完成執行並釋放事件循環以執行writeFile function 的最終任務的時間。

注意:這個答案是在一定程度上不確定的,因為我還沒有探索 NodeJS 事件循環如何徹底工作的內部結構。 我在回答這個問題時引用的文件在這里:

暫無
暫無

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

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