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 相关文章推荐
js压缩利器
Feb 20 Javascript
JavaScript DOM 学习第七章 表单的扩展
Feb 19 Javascript
JavaScript 原型继承之构造函数继承
Aug 26 Javascript
Jquery获得控件值的三种方法总结
Feb 13 Javascript
js实现简洁的滑动门菜单(选项卡)效果代码
Sep 04 Javascript
jQuery+HTML5+CSS3制作支持响应式布局时间轴插件
Aug 10 Javascript
JavaScript 数组的深度复制解析
Nov 02 Javascript
走进javascript——不起眼的基础,值和分号
Feb 24 Javascript
jquery实现的table排序功能示例
Mar 10 Javascript
js精确的加减乘除实例
Nov 14 Javascript
JS原型继承四步曲及原型继承图一览
Nov 28 Javascript
axios对请求各种异常情况处理的封装方法
Sep 25 Javascript
什么时候不能在 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
轻松入门: 煮好咖啡的七个诀窍
2021/03/03 冲泡冲煮
PHP array_flip() 删除重复数组元素专用函数
2010/05/16 PHP
.htaccess文件保护实例讲解
2011/02/06 PHP
二进制交叉权限微型php类分享
2014/02/07 PHP
Yii使用CLinkPager分页实例详解
2014/07/23 PHP
typecho插件编写教程(五):核心代码
2015/05/28 PHP
部署PHP时的4个配置修改说明
2015/10/19 PHP
PHP读取文件的常见几种方法
2016/11/03 PHP
用js实现判断当前网址的来路如果不是指定的来路就跳转到指定页面
2011/05/02 Javascript
js和jquery使按钮失效为不可用状态的方法
2014/01/26 Javascript
JS判断、校验MAC地址的2个实例
2014/05/05 Javascript
JavaScript实现找出字符串中第一个不重复的字符
2014/09/03 Javascript
纯js代码实现简单计算器
2015/12/02 Javascript
JS与jQuery遍历Table所有单元格内容的方法
2015/12/07 Javascript
js+css简单实现网页换肤效果
2015/12/29 Javascript
JQuery中attr属性和jQuery.data()学习笔记【必看】
2016/05/18 Javascript
js只执行1次的函数示例
2016/07/20 Javascript
JS实现间歇滚动的运动效果实例
2016/12/22 Javascript
清空元素html("") innerHTML="" 与 empty()的区别和应用(推荐)
2017/08/14 Javascript
[03:24]DOTA2超级联赛专访hao 大翻盘就是逆袭
2013/05/24 DOTA
python网络编程之读取网站根目录实例
2014/09/30 Python
matlab中实现矩阵删除一行或一列的方法
2018/04/04 Python
python 请求服务器的实现代码(http请求和https请求)
2018/05/25 Python
在Python中通过getattr获取对象引用的方法
2019/01/21 Python
Windows10+anacond+GPU+pytorch安装详细过程
2020/03/24 Python
阿里云:Aliyun.com
2017/02/15 全球购物
红色连衣裙精品店:Red Dress Boutique
2018/08/11 全球购物
JD Sports丹麦:英国领先的运动时尚零售商
2020/11/24 全球购物
小学教师的个人自我鉴定
2013/10/24 职场文书
应届毕业生就业自荐信
2013/10/26 职场文书
继承权公证书
2014/04/09 职场文书
电气自动化求职信
2014/06/24 职场文书
学校法制宣传月活动总结
2014/07/03 职场文书
银行贷款收入证明
2014/10/17 职场文书
影视后期实训报告
2014/11/05 职场文书
2014年学校禁毒工作总结
2014/12/23 职场文书