Node.js 学习笔记
什么是 Node.js
|
运行在服务端的javascript
它是基于 chrome javascript 运行时建立 的一个平台
它是一个事件驱动 i/o 服务端 javascript 环境,基于 google 的v8引擎,v8引擎执行javascript的速度非常快 性能非常好
|
查看 Node版本
|
node -v 或者 node -version
|
安装 Node
|
1 去官网找安装包
2 安装到这个目录 D:\Program Files\nodejs\
|
node安装完后,查看环境变量是否已配好
|
path
|
Node.js应用是由哪几部分组成
|
1 引入 required模块 我们可以使用require指令来载入 Node.js 模块
2 创建服务器:服务器可以监听客户端的请求,类似于 Apache, Nginx 等 HTTP 服务器
3 接收请求 和 响应请求: 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据
|
什么是 npm
|
PM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题
|
查看npm的版本
|
npm -v
|
npm升级
|
npm install npm -g
|
使用淘宝 npm 镜像
|
cnmp install npm -g
|
用npm安装 Node.js web 框架模块 express
|
npm install express
|
全局安装
|
npm install express -g
|
引入本地安装的包
|
require("express") ;
|
你可以使用以下命令来查看所有全局安装的模块
|
npm list -g
|
卸载模块
|
npm uninstall express
|
更新模块
|
npm update express
|
常见 npm 命令
|
npm install
npm publish
npm help
npm update
npm cache clear
|
Node.js REPL
|
交互式解释器
Read Eval Print Loop 交互式解释器 表示一个电脑环境. 我们可以在终端输入命令,并接受系统的响应
读取 读取用户输入 解析输入了Javascript数据结构并存储在内存中
执行 执行输入的数据结构
打印 输出结果
循环 循环操作以上步骤直到用户两次按下 ctrl+c 退出
|
启动 Node 终端的方法
|
node
|
回调函数
|
Node 所有 API 都支持回调函数
|
阻塞式读取文件
|
var fs = require("fs");
var data = fs.readFileSync('input.txt');
|
非阻塞式读取文件
|
var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
if (err) return console.error(err);
console.log(data.toString());}
);
|
Node.js事件事件循环
|
Node.js 是单进程 单线程应用程序,但是通过 事件 和 回调支持并发,所以性能非常高
Node.js 的每一个API都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发
Node.js 基本上所有的事件机制都是用设计模式中观察者模式实现的
Node.js 单线程类似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件发生就调用该回调函数.
|
|
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandle);
// 触发事件
eventEmitter.emit('eventName');
|
EventEmitter 类的方法
|
addListener(event, listener);
为指定事件添加一个监听器到监听器数组的尾部
on( event, listener ) ;
为指定事件注册一个监听器,接受一个字段串event和一个回调函数
once( event, listener ) ;
为指定事件注册一次单次监听器,即监听器最多只会触发一次,触发后立刻解除该监听器
removeListener()
removeAllListeners()
setMaxListeners();
listeners()
emit( event, arg0, arg1 ) ;
|
Node.js Buffer 缓冲区 11:00
|
创建一个专门存放二进制数据的缓存区
创建长度为10字节的Buffer实例
var buf = new Buffer( 10 ) ;
通过给定的数组创建Buffer实例
var buf = new Buffer([ 10, 20, 30, 40,50 ]) ;
通过字符串来创建Buffer实例
var buf = new Buffer( "www.baidu.com", "utf-8" ) ;
utf-8是默认的编码方式 此外它同样支持以下编码 "ascii" "utf8" "utf16le" "ucs2" "base64" "hex"
buf = new Buffer( 256 ) ;
len = buf.write("www.runoob.com");
len的值为 14
|
从Buffer读取数据
|
buf = new Buffer( 26 );
for( var i = 0 ; i < 26 ; i ++ ){
buf[i] = i + 97
}
buf.toString("ascii") //输出 abcdefghijklmnopqrstuvwxyz
|
将Buffer转为JSON对象
|
var buf = new Buffer( "www.runoob.com") ;
var json = buf.toJSON( buf ) ;
输出结果是
[ 119, 119, 119, 46, 114, 117, 110, 111, 111, 98, 46, 99, 111, 109 ]
|
Buffer合并
|
Buffer.concat( [ buffer1, buffer2 ] ) ;
|
Buffer比较
|
result = buffer1.compare( buffer2 ) ;
就是比较ASCII码
if(result < 0) {
console.log(buffer1 + " 在 " + buffer2 + "之前");}else if(result == 0){
console.log(buffer1 + " 与 " + buffer2 + "相同");}else {
console.log(buffer1 + " 在 " + buffer2 + "之后");}
|
拷贝Buffer
|
buffer1.copy(buffer2);
|
Buffer 裁剪
|
var buffer2 = buffer1.slice(0,2);
|
Buffer 长度
|
var buffer = new Buffer('www.runoob.com';);// 缓冲区长度
console.log("buffer length: " + buffer.length);
|
Node.js Stream 流 四种类型
|
Readable 可读操作
Writable 可写操作
Duplex 可读可写操作
Transform 操作被写入数据,然后读出结果
|
Stream会出发的事件有
|
data 当有数据可读时触发
end 没有更多的数据可读时触发
error 在接收和写入过程中发生错误时触发
finish 所有数据已被写入到底层系统时触发
|
从流中读取数据
|
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 fs = require("fs");var data = '菜鸟教程官网地址:www.runoob.com';;
// 创建一个可以写入的流,写入到文件 output.txt 中var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 编码写入数据
writerStream.write(data,'UTF8');
// 标记文件末尾
writerStream.end();
// 处理流事件 --> data, end, and error
writerStream.on('finish', function() {
console.log("写入完成。");});
writerStream.on('error', function(err){
console.log(err.stack);});
|
管道流 |
var fs = require("fs");
// 创建一个可读流var readerStream = fs.createReadStream('input.txt');
// 创建一个可写流var writerStream = fs.createWriteStream('output.txt');
// 管道读写操作// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中
readerStream.pipe(writerStream);
这样就把 readerStream 的内容转到 writeStream
|
链式流 |
var fs = require("fs");var zlib = require('zlib');
// 压缩 input.txt 文件为 input.txt.gz
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));
console.log("文件压缩完成。");
var fs = require("fs");var zlib = require('zlib');
// 解压 input.txt.gz 文件为 input.txt
fs.createReadStream('input.txt.gz')
.pipe(zlib.createGunzip())
.pipe(fs.createWriteStream('input.txt'));
console.log("文件解压完成。");
|
Node.js 模块系统
|
一个文件就是一个模块
|
服务端的模块放在哪里
|
var http = require("http") ;
|
Node.js 的 require 方法中的文件查找策略
|
1 从文件模块缓存中加载
2 从原生模块加载
3 从文件加载
|
require方法接受哪几种参数的传递
|
http fs path 原生模块
./mod 或 ../mod 相对路径的文件模块
/pathtomodule/mod 绝对路径的文件模块
mode 非原生模块的文件模块
|
匿名函数
|
支持匿名函数
|
函数传递是如何让HTTP服务器工作的 |
var http = require("http");
function onRequest(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();}
http.createServer(onRequest).listen(8888);
|
路由
|
var http = require("http");
var url = require("url");
function start( route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
route(pathname);
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;
var server = require("./server");
var router = require("./router");
server.start(router.route);
|
全局对象
|
javascript中全局对象是 window
Node.js中全局对象是 global
|
全局对象和全局变量
|
1 最外层定义的变量
2 全局对象的属性
3 隐式定义的变量
|
Node.js
|
不可能在最外层定义变量
|
__filename |
表示当前正在执行的脚本的文件名的绝对路径
|
__dirname |
表示当前执行脚本所在的目录
|
setTimeout(cb, ms) |
|
clearTimeout(t) |
|
setInterval(cb, ms) |
|
console |
|
util.inherits |
util.inherits(constructor, superConstructor)是一个实现对象间原型继承 的函数。
|
util.inspect |
util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换 为字符串的方法
showHidden 是一个可选参数,如果值为 true,将会输出更多隐藏信息。
depth 表示最大递归的层数,如果对象很复杂
|
util.isArray(object) |
|
util.isRegExp(object) |
|
util.isDate(object) |
|
util.isError(object) |
|
文件系统
|
var fs = require("fs") ;
Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,
例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
|
打开文件 |
fs.open(path, flags[, mode], callback)
|
获取文件信息 |
var fs = require('fs');
fs.stat('/Users/liuht/code/itbilu/demo/fs.js', function (err, stats) {
console.log(stats.isFile()); //true})
stats类中的方法有:
stats.isFile()
stats.isDirectory()
stats.isBlockDevice()
stats.isCharacterDevice()
stats.isSymbolicLink()
stats.isFIFO()
stats.isSocket()
|
写入文件 |
console.log("准备写入文件");
fs.writeFile('input.txt', '我是通过写入的文件内容!', function(err) {
if (err) {
return console.error(err);
}
|
读取文件 |
以下为异步模式下读取文件的语法格式:
var fs = require("fs");var buf = new Buffer(1024);
console.log("准备打开已存在的文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件:");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
console.log(bytes + " 字节被读取");
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
});});
|
关闭文件 |
var fs = require("fs");var buf = new Buffer(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件!");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
// 关闭文件
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功");
});
});});
|
截取文件 |
var fs = require("fs");var buf = new Buffer(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("截取10字节后的文件内容。");
// 截取文件
fs.ftruncate(fd, 10, function(err){
if (err){
console.log(err);
}
console.log("文件截取成功。");
console.log("读取相同的文件");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
// 关闭文件
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功!");
});
});
});});
|
截取文件 |
var fs = require("fs");var buf = new Buffer(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("截取10字节后的文件内容。");
// 截取文件
fs.ftruncate(fd, 10, function(err){
if (err){
console.log(err);
}
console.log("文件截取成功。");
|
删除文件 |
fs.unlink(path, callback)
|
创建目录 |
fs.mkdir(path[, mode], callback)
|
读取目录 |
fs.readdir(path, callback)
|
删除目录 |
fs.rmdir(path, callback)
|
Get Post
|
var http = require('http'); var url = require('url'); var util = require('util'); http.createServer(function(req, res){ res.writeHead(200, {'Content-Type': 'text/plain'}); // 解析 url 参数 var params = url.parse(req.url, true).query; res.write("网站名:" + params.name); res.write("\n"); res.write("网站 URL:" + params.url); res.end(); }).listen(3000);
|