Node.js是什么
- 不是Web框架
- 不是编程语言
- 是一个把多种技术组合起来的一个平台,运用了V8引擎、libuv、C/C++的一些库(c-ares、http_parser) 等技术
技术架构图
下面我将逐个解释重要的
bindings 绑定
C/C++实现了一个高效的http_parser库,写JS的程序员想调用这个库,直接调用肯定是不能成功的,需要一个中间的桥梁——bindings,Node.js的作者通过设计bindings模块,使JS和C/C++在数据类型上统一协调,从而顺利进行通信。
具体细节:Node.js用C++对http_parser进行封装,使它符合某些要求,封装后的文件http_parser_bindings.cpp,用Node.js提供的编译工具将其编译为.node文件。(编译成.node文件不是必须的,可以是其他的任何可行方式),这样JS代码可以直接引用这个.node文件,这样JS就能调用C++库,中间的桥梁就是binding,由于Node.js提供了很多binding,所以加个s这就是bindings。
JS和C/C++通信
- JS调用C++函数
C++的fn.cc的库写完,编译得到fn.node文件,在test.js里调用fn里的add函数
const fn=require('./当前目录/fn');
console.log(fn.add(3,5))
- C++回调JS函数:在C++函数里执行一个JS函数
const fn=require('./当前目录/fn');
fn((msg)=>{
console.log(msg)
});
C/C++插件:自定义其他能力
如果C/C++没有写这个库,我们可以用C++自己写一个库作为插件,然后bindings绑定到JS上,这样JS就可以自己调用这个C++的库了,(目前前端程序员不要求)。
libuv(Node.js重要依赖之一)
每个系统(Linux/window)都有自己的异步I/O。 I/O:所有有输入/输出过程的都是I/O,系统和外界进行交互的过程,如连接打印机,上网。
libuv(简称uv)是一个跨平台的异步I/O操作,根据系统自动选择合适的方案,可以用于:
- 操作TCP
- 操作UDP
- 解析DNS
- 读写文件等异步操作。
基于此,JS可以把以上实现全部交给C/C++去做,解决I/O瓶颈,JS只负责调用即可。
V8引擎(Node.js重要依赖之二)
功能
- 将JS源代码变成本地代码并执行
- 引擎维护JS调用栈,确保JS函数的执行顺序
- 内存管理,new Object时为所有对象分配内存
- 垃圾回收,目的:重复利用无用的内存
- 实现JS的标准库(数组的sort函数等等)
注意
- V8不提供DOM API(document.createElement是浏览器提供的)
- V8是多线程的(内存管理,垃圾回收),但是执行JS的过程是单线程的,可以开启两个线程分别执行JS
- V8本身是包含多个线程的,如垃圾回收为单独线程
- 自带Event Loop,但Node.js没有用它的,基于libuv 自己做了一个
总结
- Node.js提供的标准库简化JS代码
- Node.js用bindings让JS能和C/C++沟通:把C++的文件编译成.node文件,让JS来require
- Node.js用C/C++库更高效处理DNS/HTTP
- Node.js用V8运行用户写的JS
- Node.js用libuv进行异步I/O操作(读写文件)
- 基于libuv,Node.js自己制作了一个Event Loop用来管理事件处理顺序,先poll再check,close,timers再poll