了解node.js中的异步函数
Understanding asynchronous functions in node.js
我正在学习nodejs。我很难理解异步函数是如何工作的。我的问题与下面的代码有关。我正试图按照以下完全相同的顺序做以下事情:
- 打开文件.txt
- 读一读
- 打印其内容
- 关闭它并记录文件已关闭
- 再次打开
- 用新内容覆盖它
问题是,根据我得到的输出,我似乎没有控制这些事件的顺序。这是我在控制台中得到的输出:
只读取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.');
}
});
});
在再次调用fs.open之前,您需要等待步骤4完成。
现在你的代码看起来有点像
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")
})
});
})
});
当然,这现在看起来非常丑陋,并且neting 4+级别的深度很难阅读。你可以通过创建额外的命名函数来让它看起来更好一点
console.log("done with first file");
doThingsWithSecondFile();
或者,您可以查看async.js或promise之类的库。(如果默认情况下想要更好的错误处理,这些库特别有用)
所有这些操作都是异步的,因此您不能在代码的顶层调用fs.open('a.txt', 'r+')
——它将在fs.open('a.txt', 'r')
之后立即调用,这会导致您得到意外的结果。
看看writeToAFile()
,它在第一个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
});
});
}
相关文章:
- 如何在异步函数中使用javascript对象
- Meteor:异步函数回调异常:onAfterAction
- 未调用jquery异步函数
- 使用来自不同异步函数的响应创建一个json对象
- 如何在异步函数中正确使用Promise.all()和then()
- 从异步函数返回值
- 如何按照承诺使用mocha/chai/chai测试ES7异步函数
- 如何在将Node异步函数转换为promise时使用Q库
- 如何在异步函数与Deferredjquery之间同步
- ng用异步函数模拟怪异行为
- 用mocha测试异步函数
- 用于异步函数中的循环和定时问题
- Node.js设计:多个异步函数使用作为闭包传递的函数写入数据库
- 嵌套异步函数未及时返回数据的问题
- 在异步函数中维护变量的状态
- 递归异步函数
- Bluebird promisifyAll不会创建整个异步函数集
- 递归调用异步函数
- 异步函数调用是否可以在两个同步语句之间完成
- 如何在nodejs中实现异步函数