背景
在前端历史演变中已经提到,Nodejs的爆发从2009年开始。Nodejs的出现,基于作者Ryan Dahl 对Web开发高性能的追求,要达到高性能,异步IO/事件驱动是基本原则。对比一些高级语言,最终选择Javascript作为开发语言,由于Javascript天生的事件驱动和单线程,奠定了Nodejs编写高性能Web服务轻而易举。
简单了解Nodejs
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。
Chrome V8 引擎介绍
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 运行环境一般分为两种:
- 浏览器运行环境 ( 通常我们写的js代码要在浏览器中才能运行)
- 非浏览器运行环境 (比如Nodejs,借助于V8引擎实现运行的环境)
事件驱动
我们在Javascript中注册个事件(回调函数)。但这个事件不是马上执行。只有等事件被触发的时候,才会去执行这个事件(回调函数)。这种形式就是事件驱动。
非阻塞 I/O
阻塞:前一个程序未执行完就得一直等待。比如当你打电话问个问题时,那边说你等等我给你查查,这时候你电话仍然是挂起的,等待等待,直到拿到结果。
非阻塞:前一个程序未执行完时可以挂起,继续执行其他程序,等到使用时再执行。比如当你打电话过去问一个问题,然后挂电话,等那边找到结果就打电话给你。查问题这段时间,你该干嘛就干嘛。
I/O: 磁盘的写入(in)磁盘的读取(out)。在程序执行过程中必然要进行很多I/O操作,读写文件、输入输出、请求响应等等。I/O操作时最费时,举个例子,你要读一个文件,整个线程都暂停下来,等待文件读完后继续执行。换言之,I/O操作阻塞了代码的执行,极大地降低了程序的效率。
在Nodejs里面单线程可以通过回调函数(事件驱动)来做异步操作,达到非阻塞I/O的效果。
安装Nodejs
#安装
brew install -g node
#卸载
brew uninstall nodejs
- 使用nvm安装管理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
Nodejs 的简单使用
模块化规范 CommonJs
在前端模块化中已经对CommonJs做了介绍,并使用exports导出模块,require引入模块,实现了一个简单案例。
- require:引入一个模块
- exports: 导出模块内容
- module: 模块本身
使用Nodejs创建服务
// 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
了解基础API
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 官网。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。