zzrshuiwuhen 2019-07-14
在前端历史演变中已经提到,Nodejs的爆发从2009年开始。Nodejs的出现,基于作者Ryan Dahl 对Web开发高性能的追求,要达到高性能,异步IO/事件驱动是基本原则。对比一些高级语言,最终选择Javascript作为开发语言,由于Javascript天生的事件驱动和单线程,奠定了Nodejs编写高性能Web服务轻而易举。
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。
以上是官方给出的解释,惯例我们还是抽取关键词理解。
V8 引擎是Chrome于2008年9月2日发布开源。V8使用C++开发,相比其它的JavaScript的引擎转换成字节码或解释执行,V8将其编译成原生机器码(IA-32, x86-64, ARM, or MIPS CPUs),并且使用了如内联缓存(inline caching)等方法来提高性能。有了这些功能,JavaScript程序在V8引擎下的运行速度媲美二进制程序。
Chrome浏览器在Webkit渲染引擎中使用v8引擎来提高浏览器的渲染性能。
上图是webkit大致结构,红色部分是webkit的默认引擎,在谷歌系列产品中被替换为v8引擎;
Nodejs是站在“巨人的肩膀”上进行一系列的封装,它的高性能,离不开Chorme V8引擎。
Javascript 是一个静态脚本语言,运行时必须要借助于引擎才能运行。
Javascript 运行环境一般分为两种:
我们在Javascript中注册个事件(回调函数)。但这个事件不是马上执行。只有等事件被触发的时候,才会去执行这个事件(回调函数)。这种形式就是事件驱动。
阻塞:前一个程序未执行完就得一直等待。比如当你打电话问个问题时,那边说你等等我给你查查,这时候你电话仍然是挂起的,等待等待,直到拿到结果。
非阻塞:前一个程序未执行完时可以挂起,继续执行其他程序,等到使用时再执行。比如当你打电话过去问一个问题,然后挂电话,等那边找到结果就打电话给你。查问题这段时间,你该干嘛就干嘛。
I/O: 磁盘的写入(in)磁盘的读取(out)。在程序执行过程中必然要进行很多I/O操作,读写文件、输入输出、请求响应等等。I/O操作时最费时,举个例子,你要读一个文件,整个线程都暂停下来,等待文件读完后继续执行。换言之,I/O操作阻塞了代码的执行,极大地降低了程序的效率。
在Nodejs里面单线程可以通过回调函数(事件驱动)来做异步操作,达到非阻塞I/O的效果。
#安装 brew install -g node #卸载 brew uninstall nodejs
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash # or wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash # 放入环境变量 source ~/.bash_profile # 判断是否安装成功 nvm list # 安装node nvm install 6.14.4 # or 10.10.0, 8.9.1, etc # 判断node安装成功 node -v npm -v
在前端模块化中已经对CommonJs做了介绍,并使用exports导出模块,require引入模块,实现了一个简单案例。
// index.js const http = require('http'); const hostname = '127.0.0.1'; const port = 3000; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World\n'); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
运行 node index.js
会起一个去 127.0.0.1:3000
的服务,并在浏览器中输出Hello world
path
模块提供用于处理文件路径和目录路径的实用工具。
// 引用 const path = require('path'); path.join('/foo', 'bar', 'baz/asdf', 'quux', '..'); // 返回: '/foo/bar/baz/asdf' // path.resolve() 方法将路径或路径片段的序列解析为绝对路径 path.resolve('/foo/bar', './baz'); // 返回: '/foo/bar/baz'
fs
文件系统模块,对文件和目录进行读写操作。
// 引用 const fs = require('fs'); // 读取文件 fs.readFile('./test.txt', function(err, data) { if (err) { throw err; } console.log(data); }); // 写入文件 fs.writeFile('input.txt', '我是新写入的内容', function (err) { if (err) console.error(err); console.log('数据写入的数据'); }); // 删除 fs.unlink('/tmp/hello', (err) => { if (err) throw err; console.log('已成功删除 /tmp/hello'); }); // 重命名 fs.rename('/tmp/hello', '/tmp/world', (err) => { if (err) throw err; console.log('重命名完成'); });
更多Api
参考Nodejs Api 官网。