1.安装node.js
https://nodejs.org/dist/v10.15.1/node-v10.15.1-linux-x64.tar.xz
tar xf node-v10.15.1-linux-x64.tar.xz
mkdir -p /usr/local/node/v10.15.1
mv node-v10.15.1-linux-x64 /usr/local/node/v10.15.1
vim /etc/profile
export NODE_HOME=/usr/local/node/v10.15.1
export PATH=$NODE_HOME/bin:$PATH
source /etc/profile
2.node版本查看
node -v
3.Node.js应用是由哪几部分组成
引入required模块(载入Node.js模块)
创建服务器(服务器可以监听客户端的请求)
接收请求与响应请求
4.第一个应用(server.js)
var http = require("http");
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World, Nodejs');
}).listen(8888);
console.log('Server running at http://127.0.0.1:8888/');
5.NPM使用介绍
# 介绍
NPM是随同NodeJS一起的安装包管理工具,能解决NodeJS代码部署上的很多问题
# 查看npm版本
npm -v
# npm命令升级
npm install npm -g
# 安装模块
npm install <Module Name>
# 全部安装和本地安装
npm install express # 本地安装
npm install express -g # 全局安装
# 查看所有全局安装模块
npm list -g
# 查看某个模块版本号
npm list grunt
# 卸载模块
npm uninstall express
# 查看包是否存在
npm ls
# 更新模块
npm update express
# 搜索模块
npm search express
# 创建模块
npm init
# npm资源库注册用户发布模块
npm adduser
npm publish
# 处理相同版本号发布新代码
npm cache clear
# npm版本号(X.Y.Z)
X 有大变动,向下不兼容,更新X位
Y 新增功能,向下兼容,更新Y位
Z 修复BUG,需要更新Z位
# 使用淘宝NPM
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm install <Module Name>
6.使用package.json
name 包名
version 包的版本号
description 包的描述
homepage 包的官网URL
author 包的作者
contributors 包的其他贡献者名字
dependencies 依赖包列表
repository 包代码存放的地方的类型
main 程序的主入口文件,默认值是index.js
keywords 关键字
7.REPL(交互式解释器)
8.回调函数
# 阻塞读取文件内容
var fs = require("fs");
var data = fs.readFileSync('input.txt');
console.log(data.toString());
# 非阻塞读取文件内容
var fs = require("fs");
fs.readFile("input.txt", function (err, data) {
if (err) {
return console.error(err);
}
console.log(data.toString());
});
console.log("程序执行结束!");
9.事件循环
nodejs是单进程单线程应用程序,但是V8引擎提供异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高;几乎每一个API都是支持回调的;基本上所有的事件机制都是设计模式中观察者设计模式实现
# 事件驱动程序
var events = require('events');
var eventEmitter = new events.EventEmitter();
var connectHandler = function connected() {
console.log('连接成功');
eventEmitter.emit('data_received');
}
// 绑定connection事件处理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函数绑定data_received事件
eventEmitter.on('data_received', function(){
console.log('数据接收成功');
});
// 触发connection事件
eventEmitter.emit('connection');
console.log("程序执行完毕");
10.EventEmitter
var events = require('events');
var eventEmitter = new events.EventEmitter();
eventEmitter.setMaxListeners(2);
var listener1 = function listener1(arg1) {
console.log('监听器listener1执行 param: ' + arg1);
}
var listener2 = function listener2() {
console.log('监听器listener2执行');
}
var listener3 = function listener3() {
console.log('监听器listener3执行 once');
}
var errorListener = function listener4() {
console.log('error时触发');
}
eventEmitter.addListener('connection', listener1);
eventEmitter.on('connection', listener2);
eventEmitter.once('connection', listener3);
var eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件");
eventEmitter.emit('connection', 'first');
console.log("---------------------------");
eventEmitter.removeListener('connection', listener1);
eventEmitter.emit('connection');
eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件");
console.log("---------------------------");
var eventList = eventEmitter.listeners('connection');
console.log(eventList);
eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件");
console.log("---------------------------");
eventEmitter.removeAllListeners('connection');
eventEmitter.emit('connection');
eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " 个监听器监听连接事件");
console.log("---------------------------");
eventEmitter.on('error', errorListener);
eventEmitter.emit('error');
一般不会直接使用EventEmitter,而是在对象中继承它
11.Buffer(缓冲区)
JavaScript语言自身只有字符串数据类型,没有二进制数据类型,Buffer专门存放二进制数据的缓存区
# 字符编码(ascii/utf8/base64/latin1/binary/hex)
const buf = Buffer.from('runoob', 'ascii');
console.log(buf.toString('hex'));
console.log(buf.toString('base64'));
# 创建Buffer类
// 创建一个长度为10且用0填充的Buffer
const buf1 = Buffer.alloc(10);
// 创建一个长度为10且用0x1填充的Buffer
const buf2 = Buffer.alloc(10, 1);
// 创建一个长度为10且未初始化的Buffer
// 这个方法比调用Buffer.alloc()更快
// 但返回的Buffer实例可能包含旧数据
// 因此需要使用fill()或write()重写。
const buf3 = Buffer.allocUnsafe(10);
// 创建一个包含[0x1, 0x2, 0x3]的Buffer
const buf4 = Buffer.from([1, 2, 3]);
// 创建一个包含UTF-8字节[0x74, 0xc3, 0xa9, 0x73, 0x74]的Buffer
const buf5 = Buffer.from('test');
// 创建一个包含Latin-1字节[0x74, 0xe9, 0x73, 0x74]的Buffer
const buf6 = Buffer.from('test', 'latin1');
console.log(buf6.toString());
# 写入缓存区(buf.write(string[, offset[, length]][, encoding]))
var buf = Buffer.alloc(256);
var len = buf.write("www.runoob.com");
console.log("length: "+ len);
# 读取缓冲区(buf.toString([encoding[, start[, end]]]))
var buf = Buffer.alloc(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97;
}
console.log(buf.toString('ascii'));
console.log(buf.toString('ascii', 0, 5));
# 转json(buf.toJSON())
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
console.log(buf.toJSON())
const json = JSON.stringify(buf);
console.log(json);
const copy = JSON.parse(json, (key, value) => {
if (value && value.type === 'Buffer') {
return Buffer.from(value.data);
} else {
return value;
}
});
console.log(copy);
console.log(copy.length);
# 缓冲区合并(Buffer.concat(list[, totalLength]))
var buffer1 = Buffer.from(('buffer1 '));
var buffer2 = Buffer.from(('buffer2'));
var buffer3 = Buffer.concat([buffer1, buffer2]);
console.log("result: " + buffer3.toString());
# 缓冲区比较(buf.compare(otherBuffer))
var buffer1 = Buffer.from('ABC');
var buffer2 = Buffer.from('ABC');
var result = buffer1.compare(buffer2);
if(result === 0) {
console.log('相等');
}else {
console.log('不相等');
}
12.Stream
# Stream四种流类型
Readable 可读操作
Writable 可写操作
Duplex 可读可写操作
Transform 操作被写入数据,然后读出结果
# Stream对象都是EventEmitter实例,常用事件
data 当有数据可读时触发
end 没有更多的数据可读时触发
error 在接收和写入过程中发生错误时触发
finish 所有数据已被写入到底层系统时触发
# 从流中读取数据
var fs = require("fs");
var readerStream = fs.createReadStream('input.txt');
readerStream.setEncoding('UTF8');
var data = '';
readerStream.on('data', function(chunk) {
console.log('reading');
data += chunk;
});
readerStream.on('end',function(){
console.log('end ' + data);
});
readerStream.on('error', function(err){
console.log('error ' + err.stack);
});
console.log("程序执行完毕");
# 写入流
var fs = require("fs");
var writerStream = fs.createWriteStream('output.txt');
var data = 'write content';
writerStream.write(data,'UTF8');
writerStream.end();
writerStream.on('finish', function() {
console.log("写入完成");
});
writerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序执行完毕");
# 管道流
var fs = require("fs");
var readerStream = fs.createReadStream('input.txt');
var writerStream = fs.createWriteStream('output.txt');
readerStream.pipe(writerStream);
console.log("程序执行完毕");
# 链式流(压缩和解压)
var fs = require("fs");
var zlib = require('zlib');
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));
console.log("文件压缩完成");
var fs = require("fs");
var zlib = require('zlib');
fs.createReadStream('input.txt.gz')
.pipe(zlib.createGunzip())
.pipe(fs.createWriteStream('input.txt'));
console.log("文件解压完成");