我目前正在尝试测试一些Node.js代码。 现在,我试图弄清楚为什么我的代码console.log()相对于代码执行顺序而言是不同的顺序。这与操作系统相关的Node.js函数调用有关。
我的脚本按顺序执行此操作:
//First
fs.readdir(){ //read from a directory all the available files
console.log some stuff #a
}
//Second
fs.readFile(){ //read entire text file
console.log some stuff #b
}
//Third
//create readline interface using fs.createReadStream(filedir) then
interface{ //read from text file line by line
console.log some stuff #c
}
函数a使用以下路径:__dirname +'/ text_file /'
函数b和c使用以下路径:__dirname,'/text_file/text1.txt'
输出:
a
c
b
有人可以解释为什么发生此命令吗?我不是操作系统方面的专家,也不是Node.js在后台发生的事情。如果我要依赖此命令,是否会使我的应用程序混乱?
答案 0 :(得分:4)
如果像这样一个接一个地启动多个异步操作,则完成顺序不确定。这些操作独立于Javascript运行。它们就是所谓的“非阻塞” ,这意味着它们会立即从函数调用中返回,并且Javascript会继续执行。一段时间后,它们完成,在Javascript事件队列中插入一个事件,然后调用传递给它们的回调。这些函数的“异步,非阻塞”方面意味着,它们在返回之前不会“等待”操作完成。
同时进行的多个异步操作的完成顺序仅取决于哪个操作比另一个操作先完成。
如果希望它们按顺序运行,则必须通过在第一个操作的完成回调中启动第二个操作并在第三个操作的完成回调中启动第三个操作,对它们进行顺序编码,以使其顺序运行。
例如:
fs.readdir(somePath, function(err, files) {
if (err) {
console.log(err);
} else {
fs.readFile(someFilename, function(err, data) {
if (err) {
console.log(err);
} else {
// done with both asynchronous operations here
console.log(data);
}
});
}
});
有关该主题的其他一些相关参考文献:
How to let asynchronous readFile method follow order in node.js
How to synchronize a sequence of promises?
How do I set a specific order of execution when asynchronous calls are involved?
How does Asynchronous Javascript Execution happen? and when not to use return statement?
Single thread synchronous and asynchronous confusion
Why do callbacks functions allow us to do things asynchronously in Javascript?
答案 1 :(得分:1)
readdir
和readFile
是异步的,也就是说,它们在代码的主要流程之外进行处理。这就是为什么要给他们一个回调,该回调在操作完成后会执行,这可能需要很长时间(在计算机的时间概念上)。
您不能完全依靠异步功能完成下一条同步代码行。这意味着您的代码最终将看起来像这样:
fs.readdir(someDir, function(err, files) {
if (err) return;
// do stuff with the list of files in the directory
fs.readFile(someFile, function(err, contents) {
if (err) return;
// do stuff with the file's contents
});
});
为什么异步,您可能会问?好吧,也许您可以在(非常慢的)磁盘旋转尝试查找数据时继续做其他事情。在读取磁盘时停止整个程序会非常浪费时间,因此Node可以使依赖于磁盘或网络的此类操作异步进行,这使您可以继续执行任何其他处理,直到完成。
当然,这意味着您必须编写依赖于回调内部此类异步操作的输出的代码。
在另一个说明中:
希望您会看到,对于大型应用程序而言,这种编码风格非常麻烦,因为主代码会更偏向右侧,并且错误跟踪非常棘手。这就是发明Promise
的原因,我建议您学习它们,但是之后您会理解正常的异步性。
答案 2 :(得分:1)
与传统的编程语言不同,JavaScript(及其类似NodeJS的变体)并行运行代码,每个异步函数都独立于其他函数运行,因此该程序不会按顺序运行,这使执行速度更快,但更难执行控制
要处理同步功能,有ASYNC之类的库可以让您控制一个或多个函数结束时的处理方式,并有助于限制或消除callback hell
https://www.sohamkamani.com/blog/2016/03/14/wrapping-your-head-around-async-programming/
答案 3 :(得分:0)
所有这些功能都是异步的,将并行执行。 fs.readFile
的回调将在读取整个文件后执行,就像fs.createReadStream
的回调将在流的第一个块可读时执行,并且比第一个快。