[英]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.