definition
简单来说,Node.js 就是运行在服务端的 JavaScript。
引入 required 模块: 我们可以使用 require 指令来载入 Node.js 模块。
创建服务器: 服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
接收请求与响应请求: 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。
//1 引入http模块并实例化
var http = require("http")
2 使用 http.createServer() 创建服务器
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\n');
}).listen(8888);// 指定这个 HTTP 服务器监听的端口号
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
node终端:
- 在终端使用node启动node终端(REPL)
- Ctrl+c两次或Ctrl+d退出node交互式解释器
node事件驱动
Node.js 异步编程的直接体现就是回调。Node 所有 API 都支持回调函数。 node是多线程的:每个api都是异步的并且由独立的线程完成。
例:阻塞读取文件与非阻塞(异步)读取文件
var fs = require("fs")
//同步
var data1 = fs.readFileSync('input.txt');
console.log(data1.toString())
console.log("data1读取完毕")
异步:读取文件操作与主程序并行,读取完毕执行回调
fs.readFile('input.txt', function (err, data2) {
if (err) return console.error(err);
console.log(data2.toString());
});
console.log("data2读取完毕")
结果:data1=>data1读取完毕=>data2读取完毕=>data2
EventEmitter 的核心就是事件触发与事件监听器功能的封装。
var events = require('events');
var eventEmitter = new events.EventEmitter();
// 监听器 #1
var listener1 = function listener1() {
console.log('监听器 listener1 执行。');
}
// 监听器 #2
var listener2 = function listener2() {
console.log('监听器 listener2 执行。');
}
// 绑定 connection 事件,处理函数为 listener1
eventEmitter.addListener('connection', listener1);
// 绑定 connection 事件,处理函数为 listener2
eventEmitter.on('connection', listener2);
//listenerCount()输出当前事件有多少监听器
var eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " 个监听器监听连接事件。");
// 触发 connection 事件
eventEmitter.emit('connection');
// 移除监绑定的 listener1 函数
eventEmitter.removeListener('connection', listener1);
console.log("listener1 不再受监听。");
// 触发连接事件
eventEmitter.emit('connection');
eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection');
console.log(eventListeners + " 个监听器监听连接事件。");
console.log("程序执行完毕。");
遇到异常时会触发error事件,若没有监听error事件,Node.js 会把它当作异常,退出程序并输出错误信息。
所以需要对error事件进行监听以免程序遇到错误而奔溃
eventEmitter.on("error",function(){...})
buffer 缓冲区
由于js中没有二进制数据类型,所以在 Node.js中,定义了一个 Buffer 类,用来创建一个专门存放二进制数据的缓存区。
- 创建缓冲区:var buf = new Buffer(argu),argu可为数字,数组。以字节为单位
- 往缓冲区写入:buf.write(string[, offset[, length]][, encoding]),返回实际写入的大小。如果 buffer 空间不足, 则只会写入部分字符串。
- 从缓冲区读数据:buf.toString([encoding[, start[, end]]])
- 缓冲区合并:Buffer.concat(list[, totalLength])
- list:指定要合并的缓冲区数组
- totallen:指定合并后的长度
- 返回值:合并后的新buffer对象
- 缓冲区比较:buf.compare(otherBuffer); 返回0:相同
- 缓冲区裁剪:buf.slice([start[, end]])
stream流
node提供的一个抽象接口,可以实现读取流、写入流、管道流、链式流.。所以stream对象都可以对事件进行监听,主要的事件有:data(读数据时触发),end(没数据可读时触发),error。
var fs = require("fs");
var data = '';
// 创建可读流
var readerStream = fs.createReadStream('input.txt');
// 设置编码为 utf8。
readerStream.setEncoding('UTF8');
// 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
data += chunk;
});
readerStream.on('end',function(){
console.log(data);
});
readerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序执行完毕");
// 创建写入流
var writerStream = fs.createWriteStream('output.txt');
writerStream.write(data)
//用管道连接
readerStream.pipe(writerStream)
结果:程序执行完毕=》input.txt
node中的模块化
引入模块:
var xxx = require(模块路径)
module.export = function(){...}
路由
首先,要为路由提供请求的URL和其他需要的GET及POST参数。
随后路由需要根据这些数据来执行相应的代码。
因此,我们需要查看HTTP请求,从中提取出请求的URL以及GET/POST参数。
但是为了解析这些数据,我们需要额外的Node.JS模块,它们分别是url和querystring模块。
var http = require("http");
var url = require("url");
function start() {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;//获取路径
var jsonobj = url.parse(request.url).query //获取url中的参数列表
console.log("Request for " + pathname + " received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
全局对象
js中的全局对象为windows,而node中的全局对象为global.
常用全局对象与变量:
- __filename:输出当前执行文件路径
- __dirname:当前执行脚本所在的目录
- setTimeout(cb, ms) 全局函数在指定的毫秒(ms)数后执行指定函数(cb)。
文件系统
var fs = require('fs');
//打开文件:
fs.open(path, flags[, mode], callback)
flag:r(只读)、r+(读写)、rs(同步读)、w、wx(写入新文件,路径若存在则报错)、
//获取文件信息
fs.stat(path, callback)
//读取文件:
fs.readFile(path,cb(err,data){...})
//写入文件:
fs.writeFile(filename, data[, options], callback)
//关闭文件
fs.close(fd, callback) fd:通过fs.open返回的文件描述符
//删除文件:
fs.unlink(path, callback)
获取GET/POST请求内容
-
GET请求 get请求的内容直接嵌入在url中,所以在http.createServer(cb(req,res){...
url.parse(req.url)})
就能获取完整的get请求
-
POST请求 POST请求的内容全部的都在请求体中,但是http.ServerRequest并不会主动获取、解析请求体,没有属性是可以直接获取post的。因为对每一个post请求都获取请求体是耗费资源与时间的事情,并且无差别获取可能造成恶意攻击。
所以需要获取post请求时,需手动去缓存
http.createServer(function(req, res){
var post = ''; //定义了一个post变量,用于暂存请求体的信息
req.on('data', function(chunk){ //通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
post += chunk;
});
req.on('end', function(){ //在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(3000);
工具模块
模块名 描述
OS 模块 提供基本的系统操作函数。
Path 模块 提供了处理和转换文件路径的工具。
Net 模块 用于底层的网络通信。提供了服务端和客户端的的操作。
DNS 模块 用于解析域名。
Domain 模块 简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的。
express
流行的web服务器:Apache,Nginx。。。
Express 是一个简洁而灵活的 node.js Web应用框架, 使用 Express 可以快速地搭建一个完整功能的网站。
Express 框架核心特性:
- 可以设置中间件来响应 HTTP 请求。
- 定义了路由表用于执行不同的 HTTP 请求动作。
- 可以通过向模板传递参数来动态渲染 HTML 页面。
待补充