node.js fs.createWriteStream 中的一些问题

Some issue in node.js fs.createWriteStream

此代码似乎运行良好,但当我尝试读取最后一行中的文件 (someFile.json) 时根本不起作用。 :-( 请提供一些线索。虽然我知道这个问题很复杂。

var fs = require('fs');

var request = require("request")


var dataFile = 'data/someFile.json'
var url = "https://api.someUrl"
var file = fs.createWriteStream(dataFile);
request(url).pipe(file);

file.on('finish',function(){
    console.log('file download to ',dataFile)
    file.destroy();
    //file.closeSync;
    file.on('close', function(){ console.log('File Closed ')})
})


var datos = fs.readFileSync(dataFile, 'utf8');

您正试图在写入文件之前读取文件。您正在写入的 writeStream 是异步的。这意味着它完成了未来某个不确定的时间。同时,您的其余代码继续 运行,因此您尝试在文件完成之前阅读它。

在您的代码中,事件的顺序如下。

  1. 创建写入流
  2. 启动 http request()
  3. 使用 .pipe() 将来自 request() 的未来数据挂接到您的流中。
  4. 在流上注册 finish 事件处理程序。
  5. 调用fs.readFileSync()读取文件
  6. 数据从 request() 到达,并被发送到可以缓冲的写入流。
  7. 更多数据从 request() 到达,并被发送到可以缓冲的写入流。
  8. 请求完成,告诉 writeStream 将其数据刷新到磁盘并自行关闭。
  9. finish 事件发生。
  10. 您注册了一个 close 事件处理程序。
  11. close 事件发生。

您可能会使用流通知来执行您想要的操作,但如果只是测试文件,您可以将 fs.readFileSync() 放在写入流的关闭事件的完成句柄中。

const fs = require('fs');
const request = require("request")

const dataFile = 'data/someFile.json'
const url = "https://api.someUrl"
const file = fs.createWriteStream(dataFile);
request(url).pipe(file);

file.on('finish',function(){
    console.log('file download to ',dataFile)
}).on('close', function(){ 
   console.log('File Closed ');
   // file is available for reading now
   var datos = fs.readFileSync(dataFile, 'utf8');    
   console.log(datos);
});

此外,您不需要 .destroy() 流。默认情况下,它将设置为 autoClose,当您通过管道传输到它的流完成时,它将自动关闭。而且,您不希望 .on('close', ...) 事件处理程序位于 finish 错误处理程序中。

在这个新的建议代码中,事件的顺序如下:

  1. 创建写入流
  2. 启动 http request()
  3. 使用 .pipe() 将来自 request() 的未来数据挂接到您的流中。
  4. 在流上注册 finish 事件处理程序。
  5. 注册 close 事件处理程序。
  6. 数据从 request() 到达,并被发送到可以缓冲的写入流。
  7. 更多数据从 request() 到达,并被发送到可以缓冲的写入流。
  8. 请求完成,告诉 writeStream 将其数据刷新到磁盘并自行关闭。
  9. finish 事件发生。
  10. close 事件发生。
  11. 调用fs.readFileSync()读取文件
    var fs = require('fs');
    
    var request = require("request")

    function writeStreamToFile(filePath, stream) {
      return new Promise((resolve, reject) => {
        stream.pipe(fs.createWriteStream(filePath))
        stream.on('close', () => {
          // File ready to read
          resolve()
        })
        stream.on('finish', () => {
          // Download complete
          console.log('Download Complete')
        })
        stream.on('error', (error: any) => {
          reject(error)
      }

    })
    
    var dataFile = 'data/someFile.json'
    var url = "https://api.someUrl"
    var response = await request(url)

    var err = await writeStreamToFile(dataFile, response.data)      
    
    if(!err)
      var datos = fs.readFileSync(dataFile, 'utf8');