從node目錄刪除學(xué)習(xí)深度優(yōu)先遍歷和廣度優(yōu)先遍歷處理任務(wù)思想浑度。
使用到的模塊:fs
path
使用到的方法:(均為同步方法)
let statObj = fs.statSync(path)
:判斷是文件夾還是文件 statObj.isDirectory()
statObj.isFile()
fs.readdirSync(dir)
:返回值是一個(gè)數(shù)組穆碎,用來(lái)獲取當(dāng)前目錄下的子目錄或者文件企蹭。
fs.rmdirSync(dir)
:刪除文件夾魂那,注意:只能刪除空文件夾憔杨,不能刪除含有內(nèi)容的文件夾渐北,因此刪除文件夾采用先刪除子文件及子目錄再刪除父級(jí)文件目錄。
fs.unlinkSync(dir)
:刪除文件
path.join(path1,path2)
:將所有path片段拼接在一起多律,生成規(guī)范目錄鲜结。
深度優(yōu)先刪除目錄
思路:如下圖所示結(jié)構(gòu)雳灾,深度優(yōu)先遍歷思路就是從根節(jié)點(diǎn)A觸發(fā)钦睡,找到B之后拯钻,繼續(xù)沿著B往下找钧嘶,找到E繼續(xù)沿著E往下找棠众,發(fā)現(xiàn)E沒(méi)有子節(jié)點(diǎn),那么就將E刪除有决,接著刪除F闸拿,再刪除B,再去找C及其子節(jié)點(diǎn)书幕,然后是D及其子節(jié)點(diǎn)新荤。
function rmDirDeepSync(dir) {
let statObj = fs.statSync(dir);
if (statObj.isDirectory()) {
let dirs = fs.readdirSync(dir);
for(let i = 0; i < dirs.length; i++ ) {
rmDirDeepSync(path.join(dir, dirs[i]))
}
fs.rmdirSync(dir);
} else {
fs.unlinkSync(dir);
}
}
rmDirDeepSync('A');
廣度優(yōu)先刪除目錄
思路:如下圖所示結(jié)構(gòu),廣度優(yōu)先遍歷的思路是使用一個(gè)數(shù)組按照順序存儲(chǔ)所有的節(jié)點(diǎn)台汇,然后使用一個(gè)指針苛骨,依次向后挪動(dòng)篱瞎,指針?biāo)赶虻氖悄夸浀脑挘俅伪闅v出子節(jié)點(diǎn)智袭,并拼接至數(shù)組奔缠。然后從后到前依次刪除。
比如下圖在數(shù)組中最終是這個(gè)樣子的[ 'A', 'A/B', 'A/C', 'A/D', 'A/B/E', 'A/B/F' ]吼野。
function rmDirWideSync(dir){
let arr = [dir]; // 存儲(chǔ)數(shù)組
let index = 0; // 指針
let current; // 當(dāng)前指針指向的元素
while(current = arr[index]) {
let statObj = fs.statSync(current);
if(statObj.isDirectory()){
let dirArr = fs.readdirSync(current).map(d => path.join(current, d));
arr = [...arr, ...dirArr];
}
index++;
}
for (let i = arr.length - 1; i >=0; i--) { // 倒序刪除校哎,先刪除子級(jí),再刪除父級(jí)
let statObj = fs.statSync(arr[i]);
if(statObj.isDirectory()) {
fs.rmdirSync(arr[i]);
} else {
fs.unlinkSync(arr[i]);
}
}
}
rmDirWideSync('A');
總結(jié):同步刪除有廣度優(yōu)先和深度優(yōu)先兩種方案瞳步,異步刪除也有兩種方案闷哆,異步串行刪除,和異步并行刪除单起。
異步串行:(采用深度遞歸抱怔,深度優(yōu)先方案)
function rmDirAsyncSerie(dir,cb) {
fs.stat(dir, (err, stats) => {
if(stats.isDirectory()) {
fs.readdir(dir, (err, dirs) => {
dirs = dirs.map((item) => {
return path.resolve(dir, item);
})
function next(index) {
if(index === dirs.length) {
fs.rmdir(dir, cb);
return;
}
rmDirAsyncSerie(dirs[index], () => {
next(++index);
});
}
next(0);
})
} else {
fs.unlink(dir, cb);
}
});
}
rmDirAsyncSerie('a', () => {
console.log('刪除完成');
});
異步并行:異步的好處就是任務(wù)可以并行執(zhí)行。
function rmDirAsyncParalle(dir, cb) {
fs.stat(dir, (err, stats) => {
if(stats.isDirectory()) {
fs.readdir(dir, (err, dirs) => {
if (dirs.length === 0) {
fs.rmdir(dir, cb);
return;
}
dirs.map((d) =>{
let current = path.join(dir, d);
rmDirAsyncParalle(current, done);
})
let index = 0;
function done() {
index++;
if(index === dirs.length) {
fs.rmdir(dir, cb);
}
}
})
}else{
fs.unlink(dir, cb);
}
})
}
rmDirAsyncParalle('a', () => {
console.log('刪除成功');
})
并行刪除效率會(huì)更高嘀倒,并行和串行的區(qū)別就在于屈留,并行是在循環(huán)中執(zhí)行刪除方法的,串行是執(zhí)行完本次刪除任務(wù)后测蘑,再去調(diào)用下一個(gè)刪除方法的灌危。
注意觀察串行刪除的next方法和并行刪除的done方法。