写在前面
本文章来源于一次分享中的笔记记录。用于梳理基础概念。
名词解释
Node.js
是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用,Node.js 使用事件驱动, 非阻塞I/O 模型而得以轻量和高效,非常适合在分布式设备上运行的数据密集型的实时应用。
NPM
一个NodeJS包管理和分发工具,它可以很快的找到特定服务要使用的包,进行下载、安装以及管理已经安装的包
Express
Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架
创建服务实例
var http = require('http');
var port = 3000;
var server = http.createServer(function(req,res) {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
})
server.listen(port,function() {
console.log('Server running');
});
NodeJS特点
-
事件驱动
事件驱动模型三大要素:
事件源:能够接收外部事件的源体。
侦听器:能够接收事件源通知的对象。
事件处理程序:用于处理事件的对象。
-
非阻塞I/O
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
-
事件轮询机制
一个事件轮询拥有下面三个组件
事件队列:这是一个FIFO模型的队列,一方推入事件,另一方推出事件
队列的读取轮询线程组件,也就是主角Event Loop,
单独的线程池: 用来执行长任务(也就是threadpool,node底层,用C++写的,不会阻塞)
在NodeJS中,只有一个主线程(也就是前面说的单线程)来不断读取轮询(书中称为调用I/O观察者)队列中是否有事件。而对于读取文件,HTTP请求等比较容易堵塞的事件,就在这个单线程中执行肯定会造成堵塞,所以Event Loop会把这类型的事件交给底层的线程池执行,并给予线程池一个回调函数,当线程池操作完成这堵塞任务后,便把结果和回调函数一起再放入轮询队列中。当单线程从队列中不断读取事件,读取到这些堵塞的操作结果后,会将这些操作结果作为回调函数的输入参数,然后激活运行回调函数。
Node.js的这个单线程不只是负责读取队列事件,还会执行运行回调函数
优点:适合大量I/O计算
缺点:不适合密集的cpu计算
NodeJS部分模块介绍
- http http是Node.JS从HTTP服务器获取相应内容的主要模块
http.createServer()//返回一个新的Web服务器对象
http.listen()//在指定的主机名和端口上建立连接
- fs 处理文件系统的相关操作,例如读写文件,设置文件权限
- path
path.extname('index.html')
// Returns: '.html'
path.dirname('/foo/bar/baz/asdf/quux')
// Returns: '/foo/bar/baz/asdf'
- cluster模块
产生更多的NodeJS进程来处理系统的加载,使用相同的源代码,监听相同的端口
var cluster = require('cluster');
var numCpus = require('os').cpus().length;
cluster.isMaster//判断是否为主进程
cluster.isWorker//判断是否为子进程
cluster.worker.process.pid//获取进程pid
NodeJS代理本地文件实例
var url = require("url"),
fs=require("fs"),
http=require("http"),
path = require("path");
http.createServer(function (req, res) {
var pathname=__dirname+url.parse(req.url).pathname;//__dirname使用该全局变量的绝对路径
fs.exists(pathname,function(exists){
if(exists){
switch(path.extname(pathname)){
case ".html":
res.writeHead(200, {"Content-Type": "text/html"});
break;
case ".js":
res.writeHead(200, {"Content-Type": "text/javascript"});
break;
default:
res.writeHead(200, {"Content-Type": "application/octet-stream"});
}
fs.readFile(pathname,function (err,data){
res.end(data);
});
} else {
res.writeHead(404, {"Content-Type": "text/html"});
res.end("404 Not Found
");
}
});
}).listen(8080, "127.0.0.1");
创建Web服务
安装Express npm install express -g
- 执行Express
- 目录结构
├─bin
├─public
│ ├─images
│ ├─javascripts
│ └─stylesheets
├─routes
├─views
├─app.js
└─package.json
Express API
Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件。
中间件
中间件是一个函数,它可以访问请求对象, 响应对象, 和 web 应用中处于请求-响应循环流程中的中间件
- 执行任何代码。
- 修改请求和响应对象。
- 终结请求-响应循环。
- 调用堆栈中的下一个中间件。
路由
路由是指如何定义应用的端点(URIs)以及如何响应客户端的请求。
- HTTP请求方法
- 请求路径
- 回调函数
- 相应函数
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('hello world');
});
- Router()创建路由模块化
引用文件
NodeJS官方文档
Express4.x中文文档
Node.JS项目实践构建可扩展的Web应用书籍
了不起的NodeJS书籍
对NodeJS事件轮询的理解
事件驱动