了解node.js中的asynchronous函数
我正在学习nodejs。 我很难理解asynchronous函数是如何工作的。 我的问题与下面的代码有关。 我正在尝试按以下完全相同的顺序执行以下操作:
- 打开文件a.txt。
- 阅读。
- 打印其内容。
- closures并logging文件已closures。
- 再次打开它。
- 用新内容覆盖它。
问题是,根据我得到的输出,似乎我不控制这些事件的顺序。 这是我在控制台中获得的输出:
只读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 }); }); }