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('删除成功') })
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。