[英]Understanding asynchronous functions in node.js
I am learning nodejs. 我正在学习nodejs。 I am having some hard time understanding how asynchronous functions works.
我很难理解异步函数的工作原理。 My question is related to the code below.
我的问题与下面的代码有关。 I am trying to do the following things in the following exact same order:
我试图按照以下完全相同的顺序执行以下操作:
The problem is that as per the output I am getting, it seems that I am not controlling the sequence of these event. 问题是,根据我得到的输出,似乎我没有控制这些事件的顺序。 This is the output I am getting in the console:
这是我在控制台中得到的输出:
just read 21 bytes / this is my test files / just wrote 30 bytes /file close and ready for write 刚读了21个字节/这是我的测试文件/刚写了30个字节/关闭并准备写文件
So, as you can see, for some reason the program is writing in the file before it log that the file was closed. 因此,如您所见,由于某种原因,程序在记录文件已关闭之前正在写入文件。 I was trying to close it, log that it was closed and then to write in the file.
我试图关闭它,记录它已关闭,然后写入文件。
So I think I have a problem controlling the flow of events. 所以我认为我在控制事件流方面存在问题。 Can you point out what am I doing wrong?
您能指出我做错了什么吗?
This the the code: 这是代码:
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.');
}
});
});
All of those operations are asynchronous, so you cannot invoke fs.open('a.txt', 'r+')
at the top-level of your code - it will be invoked immediately after fs.open('a.txt', 'r')
which leads to the unexpected results you're getting. 所有这些操作都是异步的,因此您不能在代码的顶层调用
fs.open('a.txt', 'r+')
-它会在fs.open('a.txt', 'r')
会导致您得到意想不到的结果。
Take a look at writeToAFile()
which is getting invoked in a callback for first fs.close()
. 看一下
writeToAFile()
,它在第一个fs.close()
的回调中被调用。 This is the key to making sure file is first being read, closed and then wrote to and closed. 这是确保首先读取,关闭文件然后将其写入并关闭文件的关键。
Here is a fix: 解决方法:
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
});
});
}
You need to wait until step 4 is done before calling fs.open again. 您需要等到第4步完成后,才能再次调用fs.open。
Right now your code kind of looks like 现在,您的代码看起来像
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")
})
});
To preserve the order you need to nest the functions: 要保留顺序,您需要嵌套函数:
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")
})
});
})
});
Of course, this now looks very ugly and neting 4+ levels deeps is hard to read. 当然,这看起来非常丑陋,很难读取4级以上的深度。 You can make it look a little better by creating extra named functions
您可以通过创建额外的命名函数使它看起来更好一点
console.log("done with first file");
doThingsWithSecondFile();
Or you could look into libraries like async.js or promises. 或者,您可以研究async.js或promises之类的库。 (These libraries are specially useful if you want better error handling by default)
(如果您希望默认情况下更好地处理错误,这些库特别有用)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.