这两天在工作之余学习
Node.js,整理了其中一些基础api,并写了一些基础的demo下面是自己对于
path、buffer、event、fs这几个常用到api的一些用法整理。
一,PATH
模块提供了一些工具函数,用于处理文件与目录的路径。
1,path.normalize(path)
path.normalize() 方法会规范化给定的 path,并解析 '..' 和 '.' 片段
例子
const { normalize } = require('path');
console.log(normalize('/user//local/bin'));
console.log(normalize('/user//local/../bin'));
结果如图

2,path.join([...paths])
path.join() 方法使用平台特定的分隔符把全部给定的 path 片段连接到一起,并规范化生成的路径。
例子
const { normalize,join } = require('path');
console.log(join('/foo', 'bar', 'baz/asdf', 'quux', '..'));
console.log(join('/usr','../local','bin/'));
结果如图

3,path.resolve([...paths])
path.resolve() 方法会把一个路径或路径片段的序列解析为一个绝对路径。
例子
const { resolve } = require('path');
console.log(resolve('./'));
console.log(resolve('/foo/bar', './baz'));
console.log(resolve('/foo/bar', '/tmp/file/'));
结果如图

4,basename:文件名;extname:文件的拓展名;dirnam:目录名文件所在的路径
例子
const { dirname,extname,basename } = require('path');
const filePath = '/usr/local/bin/no.txt';
console.log(dirname(filePath)); // '/usr/local/bin'
console.log(extname(filePath)); // '.txt'
console.log(basename(filePath)); // 'no.txt'
结果如图

5,path.parse,path.format
path.parse() 方法返回一个对象,对象的属性表示 path 的元素。返回的对象有以下属性:root、dir、base、ext、name;
path.format() 方法会从一个对象返回一个路径字符串。 与 path.parse() 相反。
例子
const { parse,format } = require('path');
const filePath = '/usr/local/bin/node_module/package.json';
const ret = parse(filePath);
console.log(ret)
console.log(format(ret));
结果如图

需要注意的点
当 pathObject 提供的属性有组合时,有些属性的优先级比其他的高:
- 如果提供了
pathObject.dir,则pathObject.root会被忽略 - 如果提供了
pathObject.base存在,则pathObject.ext和pathObject.name会被忽略
//1, 如果提供了 `dir`、`root` 和 `base`,则返回 `${dir}${path.sep}${base}`。
// `root` 会被忽略。
path.format({
root: '/ignored',
dir: '/home/user/dir',
base: 'file.txt'
});
// 返回: '/home/user/dir/file.txt'
// 2,如果没有指定 `dir`,则 `root` 会被使用。
// 如果只提供了 `root` 或 `dir` 等于 `root`,则平台的分隔符不会被包含。
// `ext` 会被忽略。
path.format({
root: '/',
base: 'file.txt',
ext: 'ignored'
});
// 返回: '/file.txt'
// 3,如果没有指定 `base`,则 `name` + `ext` 会被使用。
path.format({
root: '/',
name: 'file',
ext: '.txt'
});
// 返回: '/file.txt'
6,sep,delimiter,win32,posix
delimiter提供平台特定的路径分隔符:
- Windows 上是
; - POSIX 上是
:
sep提供了平台特定的路径片段分隔符:
- Windows 上是
\ - POSIX 上是
/
path.win32 属性提供了 path 方法针对 Windows 的实现;
path.posix 属性提供了 path 方法针对 POSIX 的实现。
例子
// mac下
const { sep,delimiter,win32,posix } = require('path');
console.log('PATH:',process.env.PATH); // "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
console.log('sep:',sep); // "/"
console.log('win sep:',win.sep); // "\"
console.log('delimiter:',delimiter); // ":"
console.log('delimiter:',win.delimiter); // ";"
结果如图

7,关于路径的注意点
__dirname,process.cwd(),path.resolve()三者的区别
例子
//1,在项目的根目录执行:
$ ~/Desktop/node_demo $ node index.js
============代码============
const path = require('path');
const mod = require('./test.js');
console.log(mod.testVar); // 5
console.log('__dirname',__dirname); // "/Users/fujiawei/Desktop/node_demo"
console.log('process.cwd()',process.cwd()); // "/Users/fujiawei/Desktop/node_demo"
console.log('./',path.resolve('./')); // "/Users/fujiawei/Desktop/node_demo"
===================
//2,在Desktop执行
$ ~/Desktop $ node node_demo/index.js
============代码============
const path = require('path');
const mod = require('./test.js');
console.log(mod.testVar); // 5
console.log('__dirname',__dirname); // "/Users/fujiawei/Desktop/node_demo"
console.log('process.cwd()',process.cwd()); // "/Users/fujiawei/Desktop"
console.log('./',path.resolve('./')); // "/Users/fujiawei/Desktop"
-
__dirname与__filename总是返回文件的绝对路径,即物理磁盘上的路径 -
process.cwd()总是返回执行node命令时所在的文件夹路径,当前在哪里启动的脚本路径 -
./在require方法中总是相对当前文件所在文件夹的路径;在其他的地方和process.cwd()一样,相对node启动文件夹
二,buffer
Buffer处理二进制数据流;实例类似整数数组;大小固定;C++代码在V8堆外分配物理内存
1,Buffer.alloc()
-
size新建的Buffer期望的长度 -
fill用来预填充新建的Buffer的值。 默认:0 -
encoding如果fill是字符串,则该值是它的字符编码。 默认:'utf8'
分配一个大小为 size 字节的新建的 Buffer 。 如果 fill 为 undefined ,则该 Buffer 会用 0 填充。
例子
var buf1 = Buffer.alloc(10);
console.log(buf1);
结果如图

例子
var buf1 = Buffer.alloc(10,1);
console.log(buf1);
结果如图

2,Buffer.allocUnsafe()
分配一个大小为 size 字节的新建的 Buffer 。 如果 size 大于 buffer.constants.MAX_LENGTH 或小于 0,则抛出 RangeError错误。 如果 size 为 0,则创建一个长度为 0 的 Buffer。
以这种方式创建的 Buffer 实例的底层内存是未初始化的。 新创建的 Buffer 的内容是未知的,且可能包含敏感数据。 可以使用 buf.fill(0)初始化 Buffer实例为0。
例子
var buf1 = Buffer.allocUnsafe(10);
console.log(buf1);
结果如图

3,Buffer.from()
array
通过一个八位字节的 array 创建一个新的 Buffer 。
例子
var buf1 = Buffer.from([1,2,3]);
console.log(buf1);
结果如图

例子
var buf1 = Buffer.from('text'); // 默认utf8
console.log(buf1);

结果如图
var buf1 = Buffer.from('text', 'base64')
console.log(buf1);

4,Buffer.byteLength()
-
string要计算长度的值 -
encoding如果string是字符串,则这是它的字符编码。 默认:'utf8' - 返回:
string包含的字节数
返回一个字符串的实际字节长度。 这与 String.prototype.length 不同,因为那返回字符串的字符数。
例子
var buf1 = Buffer.byteLength('text')
console.log(buf1); // 4
var buf2 = Buffer.byteLength('测试')
console.log(buf2); // 6
5,Buffer.isBuffer()
如果 obj 是一个 Buffer 则返回 true ,否则返回 false 。
var buf1 = Buffer.isBuffer({})
console.log(buf1); // false
var buf2 = Buffer.isBuffer(Buffer.from([1,2,3]))
console.log(buf2); // true
6,Buffer.concat()
-
list要合并的Buffer或Uint8Array实例的数组 -
totalLength合并时list中Buffer实例的总长度 - 返回:
buffer
返回一个合并了 list 中所有 Buffer 实例的新建的 Buffer 。
例子
const buf1 = Buffer.from('this ');
const buf2 = Buffer.from('is ');
const buf3 = Buffer.from('good!');
var buf = Buffer.concat([buf1,buf2,buf3])
console.log(buf.toString());
结果如图

接下来是buffer的实例方法:
7,buf.length
返回 buf 在字节数上分配的内存量。 注意,这并不一定反映 buf 内可用的数据量。
例子
var buf = Buffer.from('good!')
console.log(buf.length); // 5
8,buf.toString()
将buffer转化为字符串
例子
var buf = Buffer.from('good!')
console.log(buf.toString()); // good!
console.log(buf.toString('base64')); // Z29vZCE=
9,buf.fill()
填充buffer。
-
value用来填充buf的值。 -
offset开始填充buf前要跳过的字节数。默认:0。 -
end结束填充buf的位置(不包含)。默认:buf.length。 -
encoding如果value是一个字符串,则这是它的字符编码。默认:'utf8'。 - 返回:
buf的引用。
如果未指定 offset 和 end,则填充整个 buf。 这个简化使得一个 Buffer 的创建与填充可以在一行内完成。
例子
var buf1 = Buffer.allocUnsafe(10);
console.log(buf1)
console.log(buf1.fill(10,2,6)); // good!
结果如图

10,buf.equals()
如果 buf 与 otherBuffer 具有完全相同的字节,则返回 true,否则返回 false。
例子
var buf4 = Buffer.from('test');
var buf5 = Buffer.from('test');
var buf6 = Buffer.from('test!');
console.log(buf4.equals(buf5)); // true
console.log(buf4.equals(buf6)); // false
11,buf.indexOf()
如javascript的indexOf的方法。
例子
var buf4 = Buffer.from('test');
console.log(buf4.indexOf('es')); // 1
console.log(buf4.indexOf('a')); // -1
12,buffer 打印例子
一个文字的字符是3,所以会出现乱码。
例子
const buf = Buffer.from('中文字符串!');
for (let i = 0;i < buf.length; i += 5) {
const b = Buffer.allocUnsafe(5);
buf.copy(b, 0, i);
console.log(b.toString());
}
const StringDecoder = require('string_decoder').StringDecoder;
const decoder = new StringDecoder('utf8');
for (let i = 0;i < buf.length; i += 5) {
const b = Buffer.allocUnsafe(5);
buf.copy(b, 0, i);
console.log(decoder.write(b));
}
结果如图

三,event,事件机制
事件驱动和异步i/o,大多数 Node.js 核心 API 都采用惯用的异步事件驱动架构,其中某些类型的对象(触发器)会周期性地触发命名事件来调用函数对象(监听器)。
所有能触发事件的对象都是 EventEmitter 类的实例。 这些对象开放了一个 eventEmitter.on() 函数,允许将一个或多个函数绑定到会被对象触发的命名事件上。 事件名称通常是驼峰式的字符串,但也可以使用任何有效的 JavaScript 属性名。
当 EventEmitter 对象触发一个事件时,所有绑定在该事件上的函数都被同步地调用。 监听器的返回值会被丢弃。
1,最简单的demo
例子
const EventEmitter = require('events');
class CustomEvent extends EventEmitter {}
const ce = new CustomEvent();
ce.on('test', ()=> {
console.log('this is test');
})
setInterval(()=>{
ce.emit('test');
},500);
结果如图

2,定制抛出错误的事件处理程序
例子
const EventEmitter = require('events');
class CustomEvent extends EventEmitter {}
const ce = new CustomEvent();
ce.on('error', (err,time) => {
console.log(err);
console.log(time);
})
ce.emit('error',new Error('失败了'), Date.now()); // 第二个是穿给时间的参数
结果如图

3,只响应一次事件
例子
const EventEmitter = require('events');
class CustomEvent extends EventEmitter {}
const ce = new CustomEvent();
ce.once('test', () => {
console.log('test event');
})
setInterval(()=>{
ce.emit('test');
},500);
结果如图

4,删除事件
分为删除事件的具体的某一个方法:ce.removeListener(事件名,具体方法)
例子
const EventEmitter = require('events');
class CustomEvent extends EventEmitter {}
const ce = new CustomEvent();
function fn1 () {
console.log('fn1');
}
function fn2 () {
console.log('fn2');
}
ce.on('test',fn1);
ce.on('test',fn2);
setInterval(()=>{
ce.emit('test');
},500);
setInterval(()=>{
// 移除某一个方法
ce.removeListener('test',fn1); // 删除test事件的fn1函数
},1500);
结果如图

删除事件所有方法,即删除事件:ce.removeAllListeners(事件名)
例子
const EventEmitter = require('events');
class CustomEvent extends EventEmitter {}
const ce = new CustomEvent();
function fn1 () {
console.log('fn1');
}
function fn2 () {
console.log('fn2');
}
ce.on('test',fn1);
ce.on('test',fn2);
setInterval(()=>{
ce.emit('test');
},500);
setInterval(()=>{
// 移除所有的事件
ce.removeAllListeners('test');
},1500);
结果如图

四,fs:文件系统
文件 I/O 是对标准 POSIX 函数的简单封装。 通过 require('fs') 使用该模块。 所有的方法都有异步和同步的形式。
异步方法的最后一个参数都是一个回调函数。 传给回调函数的参数取决于具体方法,但回调函数的第一个参数都会保留给异常。 如果操作成功完成,则第一个参数会是 null 或 undefined。
1,fs.readFile:读文件
例子
fs.readFile('./index.js',(err,data) => {
if(err) throw err;
console.log(data);
});
结果如图

buffer变成string
fs.readFile('./index.js','utf8', (err,data) => {
if(err) throw err;
console.log(data);
});
结果如图

报错:找不到相应的文件夹的时候
例子
fs.readFile('./index.jss','utf8', (err,data) => {
if(err) throw err;
console.log(data);
});
结果如图

同步读文件
const data = fs.readFileSync('./test.js','utf8');
console.log(data);
结果如图

2,写文件:fs.writeFile
例子
fs.writeFile('./test1.js','this is test','utf8',(err) => {
if(err) throw err;
console.log('done');
});
结果如图

将buffer写入到文件中去
const content = Buffer.from('this is test');
fs.writeFile('./test1.js', content, (err) => {
if(err) throw err;
console.log('done');
});
结果如图

3,文件信息:fs.stat
返回的stats有判断是否为文件和是否为文件夹的方法;
fs.stat('./index.js',(err, stats) => {
if(err) throw err;
console.log("是否为文件:",stats.isFile()); // 是否为文件
console.log("是否为文件夹:",stats.isDirectory()); // 是否为文件夹
console.log("stats详细信息:",stats);
});
结果如图

查找文件是否存在
fs.stat('./index.jsf',(err, stats) => {
if(err) {
console.log('文件不存在');
return;
};
console.log(stats.isFile()); // 是否为文件
console.log(stats.isDirectory()); // 是否为文件夹
console.log(stats);
});
结果如图

4,重命名:fs.rename:参数是要改名字的文件,需要修改成的名字,以及回调函数。
例子
fs.rename('./test1.js','test.txt', (err) => {
if(err) {
if(err) throw err;
};
console.log('done');
});
5,删除fs.unlink
例子
fs.unlink('./test.txt', (err) => {
if(err) throw err;
console.log('done');
});
6,查找文件夹fs.readdir
fs.readdir('./', (err,files) => {
if(err) throw err;
console.log(files);
});
结果如图

7,创建文件夹fs.mkdir
fs.mkdir('aaaa', (err) => {
if(err) throw err;
});
8,删除文件夹fs.rmdir
fs.rmdir('aaaa', (err) => {
if(err) throw err;
});
9,监视文件的变化fs.watch,会监视每一次文件的变化,以及变化的文件名。
fs.watch('./', {
recursive:true //是否递归
}, (eventType, filename) => { // 变化类型与变化文件名
console.log(eventType, filename);
});
结果如图

10,比较复杂的,stream是流的意思,方向与数据是条件,用到的场景看电影等
fs.createReadStream读流,pipe控制流的方向,fs.createWriteStream是创建一个流,并可以向里面写数据,这里模拟异步的方式,当随机数小于7的时候我们就往text.txt中写数据。
例子
// 创建一个stream。
const rs = fs.createReadStream('./test.js');
rs.pipe(process.stdout);// 控制方向
// 开始写stream,创建一个stream。
const ws = fs.createWriteStream('./text.txt');
const tid = setInterval(() => {
const num = parseInt(Math.random() * 10 );
console.log(num);
if(num < 7) {
ws.write(num + '');
} else {
clearInterval(tid);
ws.end();
}
}, 200);
ws.on('finish',() => {
console.log('done');
})
结果如图

写入到text.txt的值

11,解决回调地狱,我们使用promise与async await解决
例子
const promiseify = require('util').promisify;
var read = promiseify(fs.readFile);
read('./fs.js').then(data => {
console.log(data.toString());
}).catch(ex => {
console.log(ex)
})
结果如图

async await: async function在 node > 8.0 就可以使用。
const promiseify = require('util').promisify;
var read = promiseify(fs.readFile);
//
async function test() {
try{
const content = await read('./fs.js');
console.log(content.toString());
} catch (ex) {
console.log(ex)
}
}
test()
结果如图

五,参考文件
此篇文章是参考了Node.js中文网,自己写的一些api小demo
希望这篇文章对大家能有帮助,来自一个奔跑在前端路上的前端小白。
作者:darrell
链接:https://www.jianshu.com/p/08e014f786a4
来源:简书