ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
> 官网上( http://www.nodejs.org)给Node下的定义是:“一个搭建在Chrome JavaScript运行时 > 上的平台,用于构建高速、可伸缩的网络程序。 Node.js采用的事件驱动、非阻塞I/O模型,使它 > 既轻量又高效,并成为构建运行在分布式设备上的数据密集型实时程序的完美选择。” Node.js 是一个服务器端的、非阻断式I/O的、事件驱动的JavaScript运行环境。 1. 服务器端JavaScript处理:server-side JavaScript execution 2. 非阻断/异步I/O:non-blocking or asynchronous 3. I/O事件驱动:Event-driven #### 理解Node.js的异步非阻塞I/O模型 今天.NET老师在课堂上吹捧多线程编程,我就想为单线程抱个不平,因为Node的单线程异步非阻塞I/O模型,演绎了单线程编程的神话。 ##### 阻塞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了。 ##### Node.js事件轮询机制(event loop) 《Node入门》推荐我们去读一下Mixu的一篇关于事件轮询的博文,的确值得一读,我英语一般,开着词典还能勉强看,略懂吧。 Mixu说的最经典的一句话: > Everything runs in parallel except your code! (在Node中)除了代码,一切都是并行的! 理解这句话,再去学Node,也就事半功倍了!