nodejs基础之一

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基础之一

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("文件解压完成");