node中实现删除目录的几种方法


Posted in Javascript onJune 24, 2019

由于删除目录只能删除空目录(如果有子文件或文件夹要先删除)

目录结构算是典型的二叉树模型,所以涉及到遍历树结构

二叉树遍历(分为深度和广度,以及先序,中序,后序之分)

以下以深度先序解决目录删除

在node中由于主线程为单线程, 可以采取串行方式和并行方式

无论用什么方法删除,就一点核心: 如果是文件直接删除, 如果不是就删除所有子文件或子目录, 然后记得(一定记得删除自己)

深度先序(串行)

深度先序(串行 回调方式)

const fs = require('fs')
const path = require('path')
function rmdir(filePath, callback) {
  // 先判断当前filePath的类型(文件还是文件夹,如果是文件直接删除, 如果是文件夹, 去取当前文件夹下的内容, 拿到每一个递归)
  fs.stat(filePath, function(err, stat) {
    if(err) return console.log(err)
    if(stat.isFile()) {
      fs.unlink(filePath, callback)
    }else {
      fs.readdir(filePath, function(err, data) {
        if(err) return console.log(err)
        let dirs = data.map(dir => path.join(filePath, dir))
        let index = 0
        !(function next() {
          // 此处递归删除掉所有子文件 后删除当前 文件夹
          if(index === dirs.length) {
            fs.rmdir(filePath, callback)
          }else {
            rmdir(dirs[index++],next)
          }
        })()
      })
    }
  })
}

rmdir('a', function() {
  console.log('删除成功')
})

深度先序 (串行 promise写法)

const fs = require('fs')
const path = require('path')
function rmdirPromise(filePath) {
  return new Promise((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/b a/c
          let index = 0;
          (function next() {
            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('删除成功')
})

深度先序 (串行 async await写法)

// 在node v10.0.0+版本中fs模块提供 promise 写法 const fs = require('fs').promises
// 如果在node 10之前的版本中可以引入第三方模块 mz const fs = require('mz/fs') 用法一致 https://www.npmjs.com/package/mz
const fs = require('fs').promises
const path = require('path')
async function rmdirAsync(filePath) {
  let stat = await fs.stat(filePath)
  if (stat.isFile()) {
    await fs.unlink(filePath)
  } else {
    let dirs = await fs.readdir(filePath)
    dirs = dirs.map(dir => path.join(filePath, dir))
    let index = 0;
    (async function next() {
      if (index === dirs.length) {
        await fs.rmdir(filePath)
      } else {
        await rmdirAsync(dirs[index++])
        await next()
      }
    })()
  }
}

rmdirAsync('a').then(() => {
  console.log('删除成功')
}, (err) => {
  console.log('err', err)
})

深度先序 (并行)

深度先序 (并行 回调写法)

const fs = require('fs').promises
const path = require('path')

function rmdir(filePath, callback) {
  fs.stat(filePath, function(err,stat) {
    if(err) return console.log(err)
    if(stat.isFile()) {
      fs.unlink(filePath, callback)
    }else {
      fs.readdir(filePath, function(err, dirs) {
        if(err) return console.log(err)
        // 此处要添加dirs.length的验证,不然如果length为0 后面的forEach不执行, 就删不掉当前目录了, 也执行不了callback
        if(dirs.length === 0) {
          fs.rmdir(filePath, callback)
        }
        dirs = dirs.map(dir => path.join(filePath, dir))
        // 通过计数的方式来判断是否子目录都删除了
        let index = 0
        function done() {
          if(++index === dirs.length) {
            fs.rmdir(filePath, callback)
          }
        }
        // 何为并行? a下有两个目录b, c,那么同时将b, c的删除都推到event Loop中,用for循环实现
        dirs.forEach(dir => {
          // 通过done回调的方式来控制js执行流程(LazyMan问题也是这么解决的)
          rmdir(dir, done)
        });
      })
    }
  })
}
rmdir('a', function() {
  console.log('删除成功')
})

深度先行 (并行promise写法)

const fs = reqire('fs')
const path = require('path')
function rmdirPromise(filePath) {
  return new Promise((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写法)

const fs = require('fs').promises
const path = require('path')
async function rmdirAsync(filePath) {
  let stat = await fs.stat(filePath)
  if(stat.isFile()) {
    await fs.unlink(filePath)
  }else {
    let dirs = await fs.readdir(filePath)
    dirs = dirs.map(dir => rmdirAsync(path.join(filePath, dir)))
    await Promise.all(dirs)
    await fs.rmdir(filePath)
  }
}

rmdirAsync('a').then(() => {
  console.log('删除成功')
})

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery右下角自动弹出可关闭的广告层
May 08 Javascript
javascript 使用for循环时该注意的问题-附问题总结
Aug 19 Javascript
jQuery Mobile中的button按钮组件基础使用教程
May 23 Javascript
BootStrap网页中代码显示用法详解
Oct 21 Javascript
jQuery之动画效果大全
Nov 09 Javascript
详解照片瀑布流效果(js,jquery分别实现与知识点总结)
Jan 01 Javascript
js中setTimeout的妙用--防止循环超时
Mar 06 Javascript
JS实现仿UC浏览器前进后退效果的实例代码
Jul 17 Javascript
详解JS中的柯里化(currying)
Aug 17 Javascript
浅谈TypeScript 用 Webpack/ts-node 运行的配置记录
Oct 11 Javascript
JavaScript语句错误throw、try及catch实例解析
Aug 18 Javascript
vue使用vue-quill-editor富文本编辑器且将图片上传到服务器的功能
Jan 13 Vue.js
什么时候不能在 Node.js 中使用 Lock Files
Jun 24 #Javascript
vue-cli脚手架引入弹出层layer插件的几种方法
Jun 24 #Javascript
浅谈一个webpack构建速度优化误区
Jun 24 #Javascript
vue项目中运用webpack动态配置打包多种环境域名的方法
Jun 24 #Javascript
Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条
Jun 24 #Javascript
JavaScript学习教程之cookie与webstorage
Jun 23 #Javascript
React组件对子组件children进行加强的方法
Jun 23 #Javascript
You might like
理解PHP中的stdClass类
2014/04/18 PHP
smarty缓存用法分析
2014/12/16 PHP
PHP创建单例后台进程的方法示例
2017/05/23 PHP
laravel http 自定义公共验证和响应的方法
2019/09/29 PHP
Knockoutjs的环境搭建教程
2012/11/26 Javascript
关于删除时的提示处理(确定删除吗)
2013/11/03 Javascript
js全屏显示显示代码的三种方法
2013/11/11 Javascript
js实现浏览器窗口大小被改变时触发事件的方法
2015/02/02 Javascript
使用pjax实现无刷新更改页面url
2015/02/05 Javascript
javascript实时显示北京时间的方法
2015/03/12 Javascript
js实现的二级横向菜单条实例
2015/08/22 Javascript
实例讲解避免javascript冲突的方法
2016/01/03 Javascript
学习javascript面向对象 javascript实现继承的方式
2016/01/04 Javascript
Jquery uploadify上传插件使用详解
2016/01/13 Javascript
jQuery Password Validation密码验证
2016/12/30 Javascript
动态加载JavaScript文件的3种方式
2018/05/05 Javascript
Vue+Node服务器查询Mongo数据库及页面数据传递操作实例分析
2019/12/20 Javascript
JS前端模块化原理与实现方法详解
2020/03/17 Javascript
vue 输入电话号码自动按3-4-4分割功能的实现代码
2020/04/30 Javascript
[01:14]TI珍贵瞬间系列(六):冠军
2020/08/30 DOTA
python实现在无须过多援引的情况下创建字典的方法
2014/09/25 Python
简单了解python模块概念
2018/01/11 Python
flask入门之文件上传与邮件发送示例
2018/07/18 Python
Windows下python3.7安装教程
2018/07/31 Python
Python queue队列原理与应用案例分析
2019/09/27 Python
英国标志性奢侈品牌:Burberry
2016/07/28 全球购物
雅诗兰黛(Estee Lauder)英国官方网站:世界顶级化妆品牌
2016/12/29 全球购物
以实惠的价格轻松租车,免费取消:Easyrentcars
2019/07/16 全球购物
中学运动会广播稿
2014/01/19 职场文书
活动策划求职信模板
2014/04/21 职场文书
留学生求职信
2014/06/03 职场文书
2014年纪委工作总结
2014/12/05 职场文书
2015年师德师风自我评价范文
2015/03/05 职场文书
2016年暑期见闻作文
2015/11/25 职场文书
爱心捐款倡议书:点燃希望,传递温暖
2019/11/04 职场文书
用Python爬虫破解滑动验证码的案例解析
2021/05/06 Python