1.同步异步概念
同步:同步就是你要做的事你列了一个清单,按照清单上的顺序 一个一个执行
异步:就是可以同时干好几件事
阻塞:就是按照清单上的顺序一件一件的往下走,当一件事没有做完,下面的事都干不了
非阻塞:就是这件事没有干完,后面的事不会等你这件事干完了再干,而是直接开始干下一件事,等你这件事干完了,后面的事也干完了,这样就大大提高了效率
2.回调函数
Node.js 异步编程的直接体现就是回调。
回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。
例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。
回调函数一般作为函数的最后一个参数出现:
function foo1(name, age, callback) { }
function foo2(value, callback1, callback2) { }
var fs =require('fs');
//阻塞代码实例
var data=fs.readFileSync('input.txt'); //同步读取readFileSync
console.log(data.toString());
console.log("程序执行结束");
//必须等文件读取完毕才能执行console.log("程序执行结束");
var fs =require('fs');
//非阻塞代码实例 (异步)
fs.readFile("input.txt",function(err,data){
if(err) return console.log(err.message);
console.log(data.toString());
})
console.log("程序执行结束");
//先执行console.log("程序执行结束");文件读取完毕再执行console.log(data.toString());
3.事件驱动程序
- EventEmitter 类方法
- addListener(event, listener)
为指定事件添加一个监听器到监听器数组的尾部。 - on(event, listener)
为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。
//注意:addListener和on相同 - once(event, listener)
为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。 - removeListener(event, listener)
移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器。它接受两个参数,第一个是事件名称,第二个是回调函数名称。 - removeAllListeners([event])
移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。 - setMaxListeners(n)
默认情况下, EventEmitters 如果你添加的监听器超过 10 个就会输出警告信息。 setMaxListeners 函数用于提高监听器的默认限制的数量。 - listeners(event)
返回指定事件的监听器数组。 - emit(event, [arg1], [arg2], [...])
按参数的顺序执行每个监听器,如果事件有注册监听返回 true,否则返回 false。 - listenerCount(emitter, event)
返回指定事件的监听器数量。
var events = require('events');
var eventEmitter = new events.EventEmitter();
//编写监听程序
var listenner1 =function(){
console.log('listenner1');
}
var listenner2 =function(){
console.log('listenner2');
}
//绑定监听程序 listenner绑定两个
eventEmitter.on('listenner',listenner1);
eventEmitter.on('listenner',listenner2);
//触发监听
eventEmitter.emit('listenner');
//listeners(event)
console.log(eventEmitter.listeners('listenner'));
//listenerCount(emitter, event)
console.log('监听器个数'+eventEmitter.listenerCount('listenner'));
//removeListener(event, listener)
eventEmitter.removeListener('listenner',listenner1)
console.log('监听器个数'+eventEmitter.listenerCount('listenner'));
eventEmitter.emit('listenner');
- 引入 events 模块和创建 eventEmitter 对象
var events =require('events');
var eventEmitter = new events.EventEmitter();
- 事件处理程序
function connectHandler(){
console.log("link success");
eventEmitter.emit('data_received');
}
- 绑定事件处理程序:
eventEmitter.on('connection', connectHandler);
ventEmitter.on('data_received',function(){ //匿名函数的事件处理程序
console.log('no name link success');
})
- 触发事件
eventEmitter.emit('connection');
4.Buffer 类
创建一个专门存放二进制数据的缓存区,让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库
Node.js 目前支持的字符编码包括:
- ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
- utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
- utf16le - 2 或 4 个字节,小字节序编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
- ucs2 - utf16le 的别名。
- base64 - Base64 编码。
- latin1 - 一种把 Buffer 编码成一字节编码的字符串的方式。
- binary - latin1 的别名。
- hex - 将每个字节编码为两个十六进制字符。
Buffer 提供了以下 API 来创建 Buffer 类:
- Buffer.alloc(size[, fill[, encoding]]): 返回一个指定大小的 Buffer 实例,如果没有设置 fill,则默认填满 0
- Buffer.allocUnsafe(size): 返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据
- Buffer.allocUnsafeSlow(size)
- Buffer.from(array): 返回一个被 array 的值初始化的新的 Buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)
- Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer。
- Buffer.from(buffer): 复制传入的 Buffer 实例的数据,并返回一个新的 Buffer 实例
- Buffer.from(string[, encoding]): 返回一个被 string 的值初始化的新的 Buffer 实例
1). 创建 Buffer 类
//创建一个长度为 20
var buf1 = Buffer.alloc(256);
//创建一个编码为ascii
var buf2 = Buffer.from('runoob');
2). 写入缓冲区
buf.write(string[, offset[, length]][, encoding])
string - 写入缓冲区的字符串。
offset - 缓冲区开始写入的索引值,默认为 0 。
length - 写入的字节数,默认为 buffer.length
encoding - 使用的编码。默认为 'utf8' 。
var buf1 = Buffer.alloc(256);
buf1.write('buffer writer');
3). 从缓冲区读取数据
buf.toString([encoding[, start[, end]]])
encoding - 使用的编码。默认为 'utf8' 。
start - 指定开始读取的索引位置,默认为 0。
end - 结束位置,默认为缓冲区的末尾。
var buf1 = Buffer.alloc(256);
buf1.write('buffer writer');
console.log(buf1.toString('ascii',1,4));
4). 将 Buffer 转换为 JSON 对象
var json = buf2.toJSON();
5). 缓冲区合并
var buf3 = Buffer.concat([buf1,buf2]);
6). 缓冲区比较
buf.compare(otherBuffer);
返回一个数字,表示 buf 在 otherBuffer 之前,之后或相同。
var buffer1 = Buffer.from('ABC');
var buffer2 = Buffer.from('ABCD');
var result = buffer1.compare(buffer2);
7). 拷贝缓冲区
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])
8).缓冲区裁剪
buf.slice([start[, end]])
返回一个新的缓冲区,它和旧缓冲区指向同一块内存,但是从索引 start 到 end 的位置剪切。
var buffer1 = Buffer.from('runoob');
// 剪切缓冲区
var buffer2 = buffer1.slice(0,2);
9).缓冲区长度
buf.length;
5.base64
base64编码规则
base64加密解密
用记事本打开exe、jpg、pdf这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很多无法显示和打印的字符,所以,如果要让记事本这样的文本处理软件能处理二进制数据,就需要一个二进制到字符串的转换方法。Base64是一种最常见的二进制编码方法。
Base64的原理很简单,首先,准备一个包含64个字符的数组:
['A', 'B', 'C', ... 'a', 'b', 'c', ... '0', '1', ... '+', '/']
然后,对二进制数据进行处理,每3个字节一组,一共是3x8=24bit
,划为4组,每组正好6个bit:
这样我们得到4个数字作为索引,然后查表,获得相应的4个字符,就是编码后的字符串。
所以,Base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%,好处是编码后的文本数据可以在邮件正文、网页等直接显示。
如果要编码的二进制数据不是3的倍数,最后会剩下1个或2个字节怎么办?Base64用\x00字节在末尾补足后,再在编码的末尾加上1个或2个=号,表示补了多少字节,解码的时候,会自动去掉。
010011为19
010000为16