为啥说nodejs是异步非阻塞

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥说nodejs是异步非阻塞相关的知识,希望对你有一定的参考价值。

参考技术A 阻塞I/O
程序执行过程中必然要进行很多I/O操作,读写文件、输入输出、请求响应等等。I/O操作时最费时的,至少相对于代码来说,在传统的编程模式中,举个例子,你要读一个文件,整个线程都暂停下来,等待文件读完后继续执行。换言之,I/O操作阻塞了代码的执行,极大地降低了程序的效率。

下面是是一个C#读文件的例子:

private string ReadTxtToStr(string filename)

//打开文件,打开期间其他代码停止执行,直到完成打开后继续执行代码。
FileStream fs = File.Open(filename, FileMode.Open);
Console.WriteLine("我被打开文件阻塞了。");
StreamReader sr = new StreamReader(fs);
//读取文件,读取期间其他代码停止执行,直到完成读取后继续执行代码。
string str=sr.ReadToEnd();
Console.WriteLine("我被读取文件阻塞了。");
return str;

在上述代码中,两个Console.WriteLine()虽然会被执行,但是却被无辜地阻塞一段时间。理论上,如果读取这个文件需要10秒,我们就浪费了10秒在I/O等待中(实际程序运行中有很大一部分时间是浪费在I/O等待上的),在码农眼里这可是天文数字。
Having asynchronous I/O is good, because I/O is more expensive than most code and we should be doing something better than just waiting for I/O.
非阻塞I/O
理解了阻塞I/O,非阻塞I/O就好理解。非阻塞I/O是程序执行过程中,I/O操作不会阻塞程序的执行,也就是在I/O操作的同时,继续执行其他代码(这得益于Node的事件循环机制)。在I/O设备效率还远远低于CPU效率的时代,这种I/O模型(非阻塞I/O)为程序带来的性能上的提高是非常可观的。

好,下面感受一下怎么用Node.js实现非阻塞I/O,继续读文件,看码:

var fs = require("fs");
fs.readFile("./testfile", "utf8", function(error, file)
if (error) throw error;
console.log("我读完文件了!");
);
console.log("我不会被阻塞!");
复制上面代码保存为test.js,并在同一目录下新建一个名为testfile的文件,用node命令运行test.js,你将看到以下输出:

我不会被阻塞!

我读完文件了!

这显然不符合传统的程序执行顺序,注意,这就是Node.js的非阻塞I/O了。

首先解释下面程序,如果你熟悉javascript,请忽略。

var fs = require("fs");
以上代码:引入Node.js内置的File System文件系统模块fs。require()相当与Java的import,C++的include。

fs.readFile("./testfile", "utf8", function(error, file)
if (error) throw error;
console.log("我读完文件了!");
);
以上代码:进行I/O操作,给readFile绑定一个回调函数function(error,file),并在读取testfile完成后执行回调函数。期间,后面的代码继续执行,不受I/O阻塞。

这就是为什么先看到“我不会被阻塞!”而后看到“我读完文件了!”的缘故。

Node.js事件轮询机制(event loop)
《Node入门》推荐我们去读一下Mixu的一篇关于事件轮询的博文,的确值得一读,我英语一般,开着词典还能勉强看,略懂吧。

Mixu说的最经典的一句话:

Everything runs in parallel except your code!

(在Node中)除了代码,一切都是并行的!

理解这句话,再去学Node,也就事半功倍了!本回答被提问者采纳

以上是关于为啥说nodejs是异步非阻塞的主要内容,如果未能解决你的问题,请参考以下文章

nginx异步非阻塞理解

Javascript 默认是同步(阻塞)还是异步(非阻塞)

同步异步阻塞非阻塞

并发并行串行同步异步阻塞非阻塞

正确理解同步/异步和阻塞/非阻塞的区别:

node.js使用cluster实现多进程