NodeJS异步机制的疑惑

发布于 2022-09-04 15:01:05 字数 603 浏览 19 评论 0

问题描述:大家都知道nodejs因为其异步编程和事件机制而被大家津津乐道,但是最近在学习nodejs时对nodejs的异步不是很理解。都说nodejs是单进程单线程的,但是它的异步处理又给人的感觉是多线程的,比如下面的例子:

var fs = require("fs");

var data = fs.readFileSync('input.txt');//同步等待执行,这必然是单线程

console.log(data.toString());
console.log("程序执行结束!");

但是,它还有异步方式是这样处理:

var fs = require("fs");

fs.readFile('input.txt', function (err, data) {//异步执行,这个地方没有等待执行结束就已经打印了"程序执行结束",然后打印data数据
    if (err) return console.error(err);
    console.log(data.toString());
});

console.log("程序执行结束!");

希望大神们帮忙解释一下,总感觉它异步是多线程方式,而nodejs确实单进程单线程的?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

你在看孤独的风景 2022-09-11 15:01:05

node是单线程的没错,可以把这个线程理解为主线程,当遇到异步时,会把文件读取异步的任务交给底层的libuv,会根据平台选择(文件IO采用线程池,网络IO,linux采用epoll,windows采用IOCP)只是执行js代码的是单线程而已,异步任务完成后会放进事件队列,事件轮询,等到主线程空闲时取出来处理。

弃爱 2022-09-11 15:01:05

其实题主只要在网上搜一下node event loop的机制就能明白node的异步是怎么工作的了。
node底层有一个叫做libuv的东西,它与c/c++做交互,比如I/O,网络请求等等。

大概说下event loop的机制,题主最好网上搜下,深入理解下。

比如你写的例子:

    1. var fs = require("fs");

    2. fs.readFile('input.txt', 4. function (err, data) {//异步执行,这个地方没有等待执行结束就已经打印了"程序执行结束",然后打印data数据
        if (err) return console.error(err);
        console.log(data.toString());
    });
    
    3. console.log("程序执行结束!");

方便介绍,我标上了序号。它的工作机制大概是这样的:
程序运行到 1 处。引用完之后继续走,到了2处,node发现是一个异步的I/O操作,总所周知I/O操作是巨费资源的,node是单线程它真的不想干这个事情,所以呢,它就交给了libuv,并给了它一个回调函数,也就是标4的那个地方,这个回调就是在c/c++底层处理完之后,libuv就会去调用这个回调。
但在交给libuv的过程,程序是一直往下面运行的,也就到了3的地方,打印。
这就是为什么先看到打印结果后看到文件内容。

这也大概是Event Loop的工作机制,node一直把难搞的交给别人去搞,等别人搞完了,只执行一个回调而已。所以说node不适合做大量计算的工作,比如你写个while(true){}整个程序就蹦了。
node就是喜欢小计算多并发,它处理起来真的有优势,不服不行。

蓝眼睛不忧郁 2022-09-11 15:01:05

我说下我的假设,
假设读取一个文件,NODEJS发送一个读取信号(可能是发送其他什么东西,原理一样)给操作系统,此时NodeJS去干别的事了(不用等待操作系统读取文件完毕,这就是异步),操作系统读取完毕后,发送一个事件给NodeJs,NodeJs就知道文件读取完毕,通过回调函数回调执行结果。
读取文件的等待时间NodeJs拿来做别的事了,没有阻塞。

∞梦里开花 2022-09-11 15:01:05

下面的那个如果等待读取文件结束然后再打印下面的程序执行结束,那这和同步模式有啥区别吗…………
nodejs是单线程的没错,这里之所以下面的先打印出来了,因为是主进程结束之后再进行异步进程。

无畏 2022-09-11 15:01:05

node是有事件队列的

把回忆走一遍 2022-09-11 15:01:05

查下事件循环 event loop ,定时器里的函数会被放在事件队列里, 会在下一个循环里按在事件队列里放入的先后顺序执行

乖乖兔^ω^ 2022-09-11 15:01:05

node的引擎是单线程的没错 但是他底层调用的libuv不是啊 libuv在linux上网络请求用的epoll 文件读取是自己建了个线程池 在windows上面用的iocp

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文