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 相关文章推荐
javascript中日期转换成时间戳的小例子
Mar 21 Javascript
JavaScript对象学习经验整理
Oct 12 Javascript
JavaScript中按位“异或”运算符使用介绍
Mar 14 Javascript
详解AngularJS过滤器的使用
Mar 11 Javascript
浅谈javascript中的constructor
Jun 08 Javascript
jQuery.Callbacks()回调函数队列用法详解
Jun 14 Javascript
利用Angularjs实现幻灯片效果
Sep 07 Javascript
JavaScript中原型链存在的问题解析
Sep 25 Javascript
详解vue中引入stylus及报错解决方法
Sep 22 Javascript
JS使用栈判断给定字符串是否是回文算法示例
Mar 04 Javascript
ES6基础之字符串和函数的拓展详解
Aug 22 Javascript
Ajax获取node服务器数据的完整步骤
Sep 20 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
Php Mssql操作简单封装支持存储过程
2009/12/11 PHP
PHP中PDO的错误处理
2011/09/04 PHP
php cookie 详解使用实例
2016/11/03 PHP
php curl 模拟登录并获取数据实例详解
2016/12/22 PHP
php查找字符串中第一个非0的位置截取
2017/02/27 PHP
用javascript实现的激活输入框后隐藏初始内容
2007/06/29 Javascript
同一页面多个商品倒计时JS 基于面向对象的javascript
2012/02/16 Javascript
jquery Form轻松实现文件上传
2017/05/24 jQuery
手机注册发送验证码倒计时的简单实例
2017/11/15 Javascript
详解Javascript中new()到底做了些什么?
2018/03/29 Javascript
浅谈Webpack核心模块tapable解析
2018/09/11 Javascript
vue组件间的参数传递实例详解
2019/04/26 Javascript
[02:33]2014DOTA2 TI每日综述 LGD涉险晋级DK闯入胜者组
2014/07/14 DOTA
[52:20]VP vs VG Supermajor小组赛 B组胜者组决赛 BO3 第一场 6.2
2018/06/03 DOTA
跟老齐学Python之Python文档
2014/10/10 Python
使用Python压缩和解压缩zip文件的教程
2015/05/06 Python
Python使用filetype精确判断文件类型
2017/07/02 Python
python 把文件中的每一行以数组的元素放入数组中的方法
2018/04/29 Python
python django model联合主键的例子
2019/08/06 Python
python可视化篇之流式数据监控的实现
2019/08/07 Python
Python3 操作 MySQL 插入一条数据并返回主键 id的实例
2020/03/02 Python
python安装cx_Oracle和wxPython的方法
2020/09/14 Python
详解Selenium-webdriver绕开反爬虫机制的4种方法
2020/10/28 Python
Django缓存Cache使用详解
2020/11/30 Python
HTML5 Canvas画线技巧——实现绘制一个像素宽的细线
2013/08/02 HTML / CSS
UGG澳洲官网:UGG Australia
2018/04/26 全球购物
Interrail法国:乘火车探索欧洲,最受欢迎的欧洲铁路通票
2019/08/27 全球购物
彩色的非洲教学反思
2014/02/18 职场文书
运动会搞笑广播稿
2014/10/14 职场文书
教师节表彰会主持词
2015/07/06 职场文书
2016年校长新年寄语
2015/08/17 职场文书
2015年物业管理员工工作总结
2015/10/15 职场文书
创业计划书之奶茶店开店方案范本!
2019/08/06 职场文书
MySQL中存储时间的最佳实践指南
2021/07/01 MySQL
MySQL 逻辑备份 into outfile
2022/05/15 MySQL
Mysql 一主多从的部署
2022/05/20 MySQL