node中实现删除目录的几种方法
由于删除目录只能删除空目录(如果有子文件或文件夹要先删除)
目录结构算是典型的二叉树模型,所以涉及到遍历树结构
二叉树遍历(分为深度和广度,以及先序,中序,后序之分)
以下以深度先序解决目录删除
在node中由于主线程为单线程,可以采取串行方式和并行方式
无论用什么方法删除,就一点核心:如果是文件直接删除,如果不是就删除所有子文件或子目录,然后记得(一定记得删除自己)
深度先序(串行)
深度先序(串行回调方式)
constfs=require('fs')
constpath=require('path')
functionrmdir(filePath,callback){
//先判断当前filePath的类型(文件还是文件夹,如果是文件直接删除,如果是文件夹,去取当前文件夹下的内容,拿到每一个递归)
fs.stat(filePath,function(err,stat){
if(err)returnconsole.log(err)
if(stat.isFile()){
fs.unlink(filePath,callback)
}else{
fs.readdir(filePath,function(err,data){
if(err)returnconsole.log(err)
letdirs=data.map(dir=>path.join(filePath,dir))
letindex=0
!(functionnext(){
//此处递归删除掉所有子文件后删除当前文件夹
if(index===dirs.length){
fs.rmdir(filePath,callback)
}else{
rmdir(dirs[index++],next)
}
})()
})
}
})
}
rmdir('a',function(){
console.log('删除成功')
})
深度先序(串行promise写法)
constfs=require('fs')
constpath=require('path')
functionrmdirPromise(filePath){
returnnewPromise((resolve,reject)=>{
fs.stat(filePath,function(err,stat){
if(err)reject(err)
if(stat.isFile()){
fs.unlink(filePath,function(err){
if(err)reject(err)
resolve()
})
}else{
fs.readdir(filePath,function(err,dirs){
if(err)reject(err)
dirs=dirs.map(dir=>path.join(filePath,dir))//a/ba/c
letindex=0;
(functionnext(){
if(index===dirs.length){
fs.rmdir(filePath,function(err){
if(err)reject(err)
resolve()
})
}else{
rmdirPromise(dirs[index++]).then(()=>{
next()
},err=>{
reject(err)
})
}
})()
})
}
})
})
}
rmdirPromise('a').then(()=>{
console.log('删除成功')
})
深度先序(串行asyncawait写法)
//在nodev10.0.0+版本中fs模块提供promise写法constfs=require('fs').promises
//如果在node10之前的版本中可以引入第三方模块mzconstfs=require('mz/fs')用法一致https://www.npmjs.com/package/mz
constfs=require('fs').promises
constpath=require('path')
asyncfunctionrmdirAsync(filePath){
letstat=awaitfs.stat(filePath)
if(stat.isFile()){
awaitfs.unlink(filePath)
}else{
letdirs=awaitfs.readdir(filePath)
dirs=dirs.map(dir=>path.join(filePath,dir))
letindex=0;
(asyncfunctionnext(){
if(index===dirs.length){
awaitfs.rmdir(filePath)
}else{
awaitrmdirAsync(dirs[index++])
awaitnext()
}
})()
}
}
rmdirAsync('a').then(()=>{
console.log('删除成功')
},(err)=>{
console.log('err',err)
})
深度先序(并行)
深度先序(并行回调写法)
constfs=require('fs').promises
constpath=require('path')
functionrmdir(filePath,callback){
fs.stat(filePath,function(err,stat){
if(err)returnconsole.log(err)
if(stat.isFile()){
fs.unlink(filePath,callback)
}else{
fs.readdir(filePath,function(err,dirs){
if(err)returnconsole.log(err)
//此处要添加dirs.length的验证,不然如果length为0后面的forEach不执行,就删不掉当前目录了,也执行不了callback
if(dirs.length===0){
fs.rmdir(filePath,callback)
}
dirs=dirs.map(dir=>path.join(filePath,dir))
//通过计数的方式来判断是否子目录都删除了
letindex=0
functiondone(){
if(++index===dirs.length){
fs.rmdir(filePath,callback)
}
}
//何为并行?a下有两个目录b,c,那么同时将b,c的删除都推到eventLoop中,用for循环实现
dirs.forEach(dir=>{
//通过done回调的方式来控制js执行流程(LazyMan问题也是这么解决的)
rmdir(dir,done)
});
})
}
})
}
rmdir('a',function(){
console.log('删除成功')
})
深度先行(并行promise写法)
constfs=reqire('fs')
constpath=require('path')
functionrmdirPromise(filePath){
returnnewPromise((resolve,reject)=>{
fs.stat(filePath,function(err,stat){
if(err)reject(err)
if(stat.isFile()){
fs.unlink(filePath,function(err){
if(err)reject(err)
resolve()
})
}else{
fs.readdir(filePath,function(err,dirs){
if(err)reject(err)
dirs=dirs.map(dir=>path.join(filePath,dir))
dirs=dirs.map(dir=>rmdirPromise(dir))
Promise.all(dirs).then(()=>{
fs.rmdir(filePath,resolve)
})
})
}
})
})
}
rmdirPromise('a').then(()=>{
console.log('删除成功')
})
深度先序(并行async+await写法)
constfs=require('fs').promises
constpath=require('path')
asyncfunctionrmdirAsync(filePath){
letstat=awaitfs.stat(filePath)
if(stat.isFile()){
awaitfs.unlink(filePath)
}else{
letdirs=awaitfs.readdir(filePath)
dirs=dirs.map(dir=>rmdirAsync(path.join(filePath,dir)))
awaitPromise.all(dirs)
awaitfs.rmdir(filePath)
}
}
rmdirAsync('a').then(()=>{
console.log('删除成功')
})
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。