如何计算 Node.js 的执行顺序?

How to figure out order of execution for Node.js?

我目前正在尝试测试一些 Node.js 代码。 现在我想弄清楚为什么我的代码 console.log() 的顺序与代码执行顺序不同。这是关于 OS 相关的 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 后台发生的事情的专家。如果我依赖它,这个顺序会不会弄乱我的应用程序?

如果像这样一个接一个地启动多个异步操作,完成顺序是不确定的。这些操作 运行 独立于您的 Javascript。它们就是所谓的 "non-blocking" 这意味着它们 return 立即来自函数调用并且您的 Javascript 继续执行。一段时间后,他们完成,在 Javascript 事件队列中插入一个事件,然后调用您传递给他们的回调。这些函数的 "asynchronous, non-blocking" 方面意味着它们不会 "wait" 在 returning 之前完成操作。

同时进行的多个异步操作的完成顺序将仅取决于哪个先于其他操作完成工作。

如果您希望它们按顺序 运行,则必须通过在第一个完成回调中启动第二个操作并在第三个的完成回调。

例如:

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 does Asynchronous Javascript Execution happen? and when not to use return statement?

Why do callbacks functions allow us to do things asynchronously in Javascript?

readdirreadFile 是异步的,也就是说,它们在主要代码流之外进行处理。这就是为什么你要给他们一个回调,一旦操作完成就会执行回调,这可能需要很长时间(在计算机的时间概念中)。

不能依赖异步函数在下一个同步代码行执行之前完成。这意味着,您的代码最终将如下所示:

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 使依赖于磁盘或网络的此类操作异步,这使您可以继续进行任何其他处理,直到它们完成。

当然,这意味着您必须在回调中编写依赖于此类异步操作输出的代码。


在另一个注释中:

希望您能看到,对于大型应用程序,这种编码方式非常繁琐,因为主代码会向右移动更多,并且错误跟踪很棘手。这就是 Promises 被发明的原因,我建议你学习它们,但是 之后你就会理解正常的异步性。

与传统编程语言不同,JavaScript(及其变体,如 NodeJS)运行 并行代码,每个异步函数 运行 独立于其他函数,因此程序不会按顺序运行,这使得执行速度更快但更难控制

为了处理同步函数,有像 ASYNC that will allow you to control what to do when one or more functions end, and will help you limit or eliminate the callback hell

这样的库

https://www.sohamkamani.com/blog/2016/03/14/wrapping-your-head-around-async-programming/

所有这些功能都是异步的,将并行执行。 fs.readFile 将在读取整个文件后执行回调,至于 fs.createReadStream 将在流的第一个块可读时执行回调,这比第一个快。