初學(xué)node,你必須懂的幾個(gè)api

圖片發(fā)自簡書App

這兩天在工作之余學(xué)習(xí)Node.js,整理了其中一些基礎(chǔ)api,并寫了一些基礎(chǔ)的demo

下面是自己對(duì)于path、bufferevent、fs這幾個(gè)常用到api的一些用法整理。

一,PATH

模塊提供了一些工具函數(shù),用于處理文件與目錄的路徑。

1,path.normalize(path)

path.normalize() 方法會(huì)規(guī)范化給定的 path,并解析 '..''.' 片段

例子

const { normalize } = require('path');

console.log(normalize('/user//local/bin'));
console.log(normalize('/user//local/../bin'));

結(jié)果如圖

path1.png

2,path.join([...paths])

path.join() 方法使用平臺(tái)特定的分隔符把全部給定的 path 片段連接到一起,并規(guī)范化生成的路徑。

例子

const { normalize,join } = require('path');

console.log(join('/foo', 'bar', 'baz/asdf', 'quux', '..'));
console.log(join('/usr','../local','bin/'));

結(jié)果如圖

path_join.png

3,path.resolve([...paths])

path.resolve() 方法會(huì)把一個(gè)路徑或路徑片段的序列解析為一個(gè)絕對(duì)路徑。

例子

const { resolve } = require('path');

console.log(resolve('./'));
console.log(resolve('/foo/bar', './baz'));
console.log(resolve('/foo/bar', '/tmp/file/'));

結(jié)果如圖

path_resolve.png

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'

結(jié)果如圖

pathName.png

5,path.parse,path.format

path.parse() 方法返回一個(gè)對(duì)象,對(duì)象的屬性表示 path 的元素。返回的對(duì)象有以下屬性:root、dirbase、extname;

path.format() 方法會(huì)從一個(gè)對(duì)象返回一個(gè)路徑字符串。 與 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));

結(jié)果如圖

parse_format.png

需要注意的點(diǎn)

當(dāng) pathObject 提供的屬性有組合時(shí),有些屬性的優(yōu)先級(jí)比其他的高:

  • 如果提供了 pathObject.dir,則 pathObject.root 會(huì)被忽略
  • 如果提供了 pathObject.base 存在,則 pathObject.extpathObject.name 會(huì)被忽略
//1, 如果提供了 `dir`、`root` 和 `base`,則返回 `${dir}${path.sep}${base}`。
// `root` 會(huì)被忽略。
path.format({
  root: '/ignored',
  dir: '/home/user/dir',
  base: 'file.txt'
});
// 返回: '/home/user/dir/file.txt'

// 2,如果沒有指定 `dir`,則 `root` 會(huì)被使用。
// 如果只提供了 `root` 或 `dir` 等于 `root`,則平臺(tái)的分隔符不會(huì)被包含。
// `ext` 會(huì)被忽略。
path.format({
  root: '/',
  base: 'file.txt',
  ext: 'ignored'
});
// 返回: '/file.txt'

// 3,如果沒有指定 `base`,則 `name` + `ext` 會(huì)被使用。
path.format({
  root: '/',
  name: 'file',
  ext: '.txt'
});
// 返回: '/file.txt'

6,sepdelimiterwin32,posix

delimiter提供平臺(tái)特定的路徑分隔符:

  • Windows 上是 ;
  • POSIX 上是 :

sep提供了平臺(tái)特定的路徑片段分隔符:

  • Windows 上是 \
  • POSIX 上是 /

path.win32 屬性提供了 path 方法針對(duì) Windows 的實(shí)現(xiàn);

path.posix 屬性提供了 path 方法針對(duì) POSIX 的實(shí)現(xiàn)。

例子

// 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); // ";"

結(jié)果如圖

win.png

7,關(guān)于路徑的注意點(diǎn)

__dirname,process.cwd()path.resolve()三者的區(qū)別

例子

//1,在項(xiàng)目的根目錄執(zhí)行:
$ ~/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執(zhí)行
$ ~/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總是返回文件的絕對(duì)路徑,即物理磁盤上的路徑
  • process.cwd()總是返回執(zhí)行node命令時(shí)所在的文件夾路徑,當(dāng)前在哪里啟動(dòng)的腳本路徑
  • ./require方法中總是相對(duì)當(dāng)前文件所在文件夾的路徑;在其他的地方和process.cwd()一樣,相對(duì)node啟動(dòng)文件夾

二,buffer

Buffer處理二進(jìn)制數(shù)據(jù)流;實(shí)例類似整數(shù)數(shù)組;大小固定;C++代碼在V8堆外分配物理內(nèi)存

1,Buffer.alloc()

  • size 新建的 Buffer 期望的長度
  • fill 用來預(yù)填充新建的 Buffer 的值。 默認(rèn): 0
  • encoding 如果 fill 是字符串,則該值是它的字符編碼。 默認(rèn): 'utf8'

分配一個(gè)大小為 size 字節(jié)的新建的 Buffer 。 如果 fillundefined ,則該 Buffer 會(huì)用 0 填充。

例子

var buf1 = Buffer.alloc(10);
console.log(buf1);

結(jié)果如圖

buffer1.png

例子

var buf1 = Buffer.alloc(10,1);
console.log(buf1);

結(jié)果如圖

buffer2.png

2,Buffer.allocUnsafe()

分配一個(gè)大小為 size 字節(jié)的新建的 Buffer 。 如果 size 大于 buffer.constants.MAX_LENGTH 或小于 0,則拋出 RangeError錯(cuò)誤。 如果 size 為 0,則創(chuàng)建一個(gè)長度為 0 的 Buffer

以這種方式創(chuàng)建的 Buffer 實(shí)例的底層內(nèi)存是未初始化的。 新創(chuàng)建的 Buffer 的內(nèi)容是未知的,且可能包含敏感數(shù)據(jù)。 可以使用 buf.fill(0)初始化 Buffer實(shí)例為0。

例子

var buf1 = Buffer.allocUnsafe(10);
console.log(buf1);

結(jié)果如圖

buffer3.png

3,Buffer.from()

  • array

通過一個(gè)八位字節(jié)的 array 創(chuàng)建一個(gè)新的 Buffer 。

例子

var buf1 = Buffer.from([1,2,3]);
console.log(buf1);

結(jié)果如圖

buffer4.png

例子

var buf1 = Buffer.from('text'); // 默認(rèn)utf8
console.log(buf1);
buffer5.png

結(jié)果如圖

var buf1 = Buffer.from('text', 'base64')
console.log(buf1);
buffer6.png

4,Buffer.byteLength()

  • string 要計(jì)算長度的值
  • encoding 如果 string 是字符串,則這是它的字符編碼。 默認(rèn): 'utf8'
  • 返回: string 包含的字節(jié)數(shù)

返回一個(gè)字符串的實(shí)際字節(jié)長度。 這與 String.prototype.length 不同,因?yàn)槟欠祷刈址?strong>字符數(shù)。

例子

var buf1 = Buffer.byteLength('text')
console.log(buf1);   // 4

var buf2 = Buffer.byteLength('測(cè)試')
console.log(buf2);   // 6

5,Buffer.isBuffer()

如果 obj 是一個(gè) 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 要合并的 BufferUint8Array實(shí)例的數(shù)組
  • totalLength 合并時(shí) listBuffer 實(shí)例的總長度
  • 返回: buffer

返回一個(gè)合并了 list 中所有 Buffer 實(shí)例的新建的 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());  

結(jié)果如圖

bufferconcat.png
接下來是buffer的實(shí)例方法:

7,buf.length

返回 buf 在字節(jié)數(shù)上分配的內(nèi)存量。 注意,這并不一定反映 buf 內(nèi)可用的數(shù)據(jù)量。

例子

var buf = Buffer.from('good!')
console.log(buf.length); // 5

8,buf.toString()

buffer轉(zhuǎn)化為字符串

例子

var buf = Buffer.from('good!')
console.log(buf.toString());            // good!
console.log(buf.toString('base64'));    // Z29vZCE=

9,buf.fill()

填充buffer。

  • value 用來填充 buf 的值。
  • offset 開始填充 buf 前要跳過的字節(jié)數(shù)。默認(rèn): 0。
  • end 結(jié)束填充 buf 的位置(不包含)。默認(rèn): buf.length。
  • encoding 如果 value 是一個(gè)字符串,則這是它的字符編碼。默認(rèn): 'utf8'。
  • 返回: buf 的引用。

如果未指定 offsetend,則填充整個(gè) buf。 這個(gè)簡化使得一個(gè) Buffer 的創(chuàng)建與填充可以在一行內(nèi)完成。

例子

var buf1 = Buffer.allocUnsafe(10);
console.log(buf1)
console.log(buf1.fill(10,2,6)); // good!

結(jié)果如圖

bufferfill.png

10,buf.equals()

如果 bufotherBuffer 具有完全相同的字節(jié),則返回 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()

javascriptindexOf的方法。

例子

var buf4 = Buffer.from('test');
console.log(buf4.indexOf('es'));  // 1
console.log(buf4.indexOf('a'));   // -1

12,buffer 打印例子

一個(gè)文字的字符是3,所以會(huì)出現(xiàn)亂碼。

例子

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));
}

結(jié)果如圖

打印亂碼.png

三,event,事件機(jī)制

事件驅(qū)動(dòng)和異步i/o,大多數(shù) Node.js 核心 API 都采用慣用的異步事件驅(qū)動(dòng)架構(gòu),其中某些類型的對(duì)象(觸發(fā)器)會(huì)周期性地觸發(fā)命名事件來調(diào)用函數(shù)對(duì)象(監(jiān)聽器)。

所有能觸發(fā)事件的對(duì)象都是 EventEmitter 類的實(shí)例。 這些對(duì)象開放了一個(gè) eventEmitter.on() 函數(shù),允許將一個(gè)或多個(gè)函數(shù)綁定到會(huì)被對(duì)象觸發(fā)的命名事件上。 事件名稱通常是駝峰式的字符串,但也可以使用任何有效的 JavaScript 屬性名。

當(dāng) EventEmitter 對(duì)象觸發(fā)一個(gè)事件時(shí),所有綁定在該事件上的函數(shù)都被同步地調(diào)用。 監(jiān)聽器的返回值會(huì)被丟棄。

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);

結(jié)果如圖

event1.gif

2,定制拋出錯(cuò)誤的事件處理程序

例子

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()); // 第二個(gè)是穿給時(shí)間的參數(shù)

結(jié)果如圖

event2.png

3,只響應(yīng)一次事件

例子

const EventEmitter = require('events');
class CustomEvent extends EventEmitter {}
const ce = new CustomEvent();

ce.once('test', () => {
    console.log('test event');
})

setInterval(()=>{
    ce.emit('test');
},500);

結(jié)果如圖

event3.gif

4,刪除事件

分為刪除事件的具體的某一個(gè)方法: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(()=>{
    // 移除某一個(gè)方法
    ce.removeListener('test',fn1);  // 刪除test事件的fn1函數(shù)
},1500);

結(jié)果如圖

event4.gif

刪除事件所有方法,即刪除事件: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);

結(jié)果如圖

event6.gif

四,fs:文件系統(tǒng)

文件 I/O 是對(duì)標(biāo)準(zhǔn) POSIX 函數(shù)的簡單封裝。 通過 require('fs') 使用該模塊。 所有的方法都有異步和同步的形式。

異步方法的最后一個(gè)參數(shù)都是一個(gè)回調(diào)函數(shù)。 傳給回調(diào)函數(shù)的參數(shù)取決于具體方法,但回調(diào)函數(shù)的第一個(gè)參數(shù)都會(huì)保留給異常。 如果操作成功完成,則第一個(gè)參數(shù)會(huì)是 nullundefined

1,fs.readFile:讀文件

例子

fs.readFile('./index.js',(err,data) => {
    if(err) throw err;
    console.log(data);
});

結(jié)果如圖

讀文件.png

buffer變成string

fs.readFile('./index.js','utf8', (err,data) => {
    if(err) throw err;
    console.log(data);
});

結(jié)果如圖

bufferstring.png

報(bào)錯(cuò):找不到相應(yīng)的文件夾的時(shí)候

例子

fs.readFile('./index.jss','utf8', (err,data) => {
    if(err) throw err;
    console.log(data);
});

結(jié)果如圖

報(bào)錯(cuò).png

同步讀文件

const data = fs.readFileSync('./test.js','utf8');
console.log(data);

結(jié)果如圖

同步.png

2,寫文件:fs.writeFile

例子

fs.writeFile('./test1.js','this is test','utf8',(err) => {
    if(err) throw err;
    console.log('done');
});

結(jié)果如圖

寫文件1.png

buffer寫入到文件中去

const content = Buffer.from('this is test');

fs.writeFile('./test1.js', content, (err) => {
    if(err) throw err;
    console.log('done');
});

結(jié)果如圖

寫文件2.png

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詳細(xì)信息:",stats);
});

結(jié)果如圖

信息1.png
查找文件是否存在
fs.stat('./index.jsf',(err, stats) => {
    if(err) {
        console.log('文件不存在');
        return;
    };
    
    console.log(stats.isFile());   // 是否為文件
    console.log(stats.isDirectory());  // 是否為文件夾
    console.log(stats);
});

結(jié)果如圖

信息2.png

4,重命名:fs.rename:參數(shù)是要改名字的文件,需要修改成的名字,以及回調(diào)函數(shù)。

例子

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);
});

結(jié)果如圖

查找文件夾.png

7,創(chuàng)建文件夾fs.mkdir

fs.mkdir('aaaa', (err) => {
    if(err) throw err;
});

8,刪除文件夾fs.rmdir

fs.rmdir('aaaa', (err) => {
    if(err) throw err;
});

9,監(jiān)視文件的變化fs.watch,會(huì)監(jiān)視每一次文件的變化,以及變化的文件名。

fs.watch('./', {
    recursive:true //是否遞歸
}, (eventType, filename) => { // 變化類型與變化文件名
    console.log(eventType, filename);
});

結(jié)果如圖

watch.png

10,比較復(fù)雜的,stream是流的意思,方向與數(shù)據(jù)是條件,用到的場(chǎng)景看電影等

fs.createReadStream讀流,pipe控制流的方向,fs.createWriteStream是創(chuàng)建一個(gè)流,并可以向里面寫數(shù)據(jù),這里模擬異步的方式,當(dāng)隨機(jī)數(shù)小于7的時(shí)候我們就往text.txt中寫數(shù)據(jù)。

例子

// 創(chuàng)建一個(gè)stream。
const rs = fs.createReadStream('./test.js');

rs.pipe(process.stdout);// 控制方向

// 開始寫stream,創(chuàng)建一個(gè)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');
})

結(jié)果如圖

stream.png

寫入到text.txt的值

stream2.png

11,解決回調(diào)地獄,我們使用promiseasync 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)
})

結(jié)果如圖

promise.png
async await: async functionnode > 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()

結(jié)果如圖

async function.png

五,參考文件

此篇文章是參考了Node.js中文網(wǎng),自己寫的一些apidemo

希望這篇文章對(duì)大家能有幫助,來自一個(gè)奔跑在前端路上的前端小白。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測(cè)試 ...
    KeKeMars閱讀 6,610評(píng)論 0 6
  • Node.js是目前非?;馃岬募夹g(shù),但是它的誕生經(jīng)歷卻很奇特。 眾所周知,在Netscape設(shè)計(jì)出JavaScri...
    w_zhuan閱讀 3,737評(píng)論 2 41
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 7,382評(píng)論 0 17
  • 文件系統(tǒng)模塊是一個(gè)封裝了標(biāo)準(zhǔn)的 POSIX 文件 I/O 操作的集合。通過require('fs')使用這個(gè)模塊。...
    保川閱讀 940評(píng)論 0 0
  • 唐朝時(shí),有個(gè)美男子,名字喚作白衣,出身名門。他溫文爾雅的氣質(zhì),眉清目秀的臉龐,又有吟詩作對(duì)的才華,在唐朝,擁有了...
    一只特立獨(dú)行的豬與阿飛閱讀 443評(píng)論 8 7

友情鏈接更多精彩內(nèi)容