了解node.js中的asynchronous函数

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

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

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

只读21个字节/这是我的testing文件/只写了30字节/文件closures,并准备写入

所以,正如你所看到的,出于某种原因,程序在文件被closures之前正在写文件。 我试图closures它,logging它被closures,然后写入文件。

所以我认为我有一个控制事件stream的问题。 你能指出我做错了什么吗?

这个代码:

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步完成后才再次调用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+以上的水平也难以阅读。 通过创build额外的命名函数,可以使它看起来更好一些

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

或者你可以看看像async.js或承诺的图书馆。 (如果您希望默认情况下更好的error handling,这些库特别有用)

所有这些操作都是asynchronous的,所以你不能在代码的顶层调用fs.open('a.txt', 'r+') – 它会在fs.open('a.txt', 'r') ,这导致了你意想不到的结果。

看看在第一个fs.close()的callbackfs.close()调用fs.close() 。 这是确保文件首先被读取,closures然后写入和closures的关键。

这是一个修复:

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