1

我正在学习nodejs。我很难理解异步函数的工作原理。我的问题与下面的代码有关。我正在尝试按照以下完全相同的顺序执行以下操作:

  1. 打开文件 a.txt。
  2. 阅读。
  3. 打印其内容。
  4. 关闭它并记录文件已关闭。
  5. 再次打开它。
  6. 用新内容覆盖它。

问题是,根据我得到的输出,似乎我没有控制这些事件的顺序。这是我在控制台中得到的输出:

只读取 21 个字节 / 这是我的测试文件 / 只写了 30 个字节 / 文件关闭并准备写入

因此,如您所见,由于某种原因,程序在记录文件已关闭之前正在写入文件。我试图关闭它,记录它已关闭,然后写入文件。

所以我认为我在控制事件流程时遇到了问题。你能指出我做错了什么吗?

这是代码:

var fs = require('fs');

//What I am trying to do here is: open a file a.txt, read it, print its content and then //close the file and log that it has been closed.
//Then, open it again and overwrite it.

fs.open('a.txt', 'r', function(err, fd){
    if(err){throw err;}
    var readBuffer = new Buffer(1024);
    var bufferOffset = 0;
    var filePosition = 0;
    var readBufferLength = readBuffer.length;

    fs.read(fd, readBuffer, bufferOffset, readBufferLength, filePosition, function(err, readBytes){
    if(err){throw err;}
    console.log('just read ' + readBytes + ' bytes');
    console.log(readBuffer.slice(0,readBytes).toString());
    fs.close(fd,function(){
        console.log('file close and ready for write');
    });
    });




});


fs.open('a.txt', 'r+', function(err,fd){
    if(err){throw err;}
    var writeBuffer = new Buffer('saul lugo overwrote this file!');
    var bufferOffset = 0;
    var writeBufferLength = writeBuffer.length;
    var filePosition = null;

    fs.write(fd, writeBuffer, bufferOffset, writeBufferLength, filePosition, function(err, writeBytes){
    if(err){throw err;}
    if(writeBytes>0){
        console.log('just wrote ' + writeBytes + ' bytes.');
    }
    });
});
4

2 回答 2

1

所有这些操作都是异步的,因此您不能fs.open('a.txt', 'r+')在代码的顶层调用 - 它将立即被调用,fs.open('a.txt', 'r')这会导致您得到意想不到的结果。

看看在writeToAFile()first 的回调中调用了哪个fs.close()。这是确保文件首先被读取、关闭、然后写入和关闭的关键。

这是一个修复:

var fs = require('fs');

fs.open('a.txt', 'r', function(err, fd){
    // do stuff ...

    fs.read(/* params */, function(err, readBytes){
      // do stuff ...

      fs.close(fd,function(){
        // now open file again for writing
        writeToAFile();
      });
    });
});

// This will be called inside the callback handler for closing the file.
// This way file will be opened for reading, read, close and THEN opened for writing.
function writeToAFile () {
  fs.open('a.txt', 'r+', function(err,fd){
    // do stuff ...

    fs.write(/* params */, function(err, writeBytes){
      // do stuff ...

      // close file
    });
  });
}
于 2013-08-27T20:08:04.410 回答
1

您需要等到第 4 步完成后再调用 fs.open。

现在你的代码看起来像

fs.open("a.txt", function(){
    foo(function(){
       console.log("done with first file")
    })
});

fs.open("a.txt", function(){
    foo(function(){
      console.log("done with second file")
    })
});

要保留您需要嵌套函数的顺序:

fs.open("a.txt", function(){
    foo(function(){
       console.log("done with first file")

       fs.open("a.txt", function(){
           foo(function(){
               console.log("done with second file")
           })
        });
    })
});

当然,这现在看起来很丑陋,而且 4 级以上的深度很难阅读。您可以通过创建额外的命名函数使其看起来更好一些

  console.log("done with first file");
  doThingsWithSecondFile();

或者您可以查看 async.js 或 Promise 之类的库。(如果您希望默认更好地处理错误,这些库特别有用)

于 2013-08-27T20:09:40.247 回答