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 相关文章推荐
彪哥1.1(智能表格)提供下载
Sep 07 Javascript
Prototype使用指南之selector.js
Jan 10 Javascript
基于jquery的跨域调用文件
Nov 19 Javascript
jquery队列queue与原生模仿其实现方法分享
Mar 25 Javascript
js点击列表文字对应该行显示背景颜色的实现代码
Aug 05 Javascript
简单实现js选项卡切换效果
Feb 03 Javascript
微信小程序 wxapp导航 navigator详解
Oct 31 Javascript
vue实现百度搜索下拉提示功能实例
Jun 14 Javascript
搭建element-ui的Vue前端工程操作实例
Feb 23 Javascript
vue的过滤器filter实例详解
Sep 17 Javascript
vue element-ui实现input输入框金额数字添加千分位
Dec 29 Javascript
Node.js实现批量下载图片简单操作示例
Jan 18 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中curl、fsocket、file_get_content三个函数的使用比较
2014/05/09 PHP
PHP实现QQ登录实例代码
2016/01/14 PHP
php与c 实现按行读取文件实例代码
2017/01/03 PHP
PHP PDOStatement::debugDumpParams讲解
2019/01/30 PHP
JSON+JavaScript处理JSON的简单例子
2013/03/20 Javascript
tangram框架响应式加载图片方法
2013/11/21 Javascript
JavaScript中遍历对象的property的3种方法介绍
2014/12/30 Javascript
jquery实现公告翻滚效果
2015/02/27 Javascript
JavaScript检查数字是否为整数或浮点数的方法
2015/06/09 Javascript
javascript返回顶部的按钮实现方法
2016/01/09 Javascript
编写高质量JavaScript代码的基本要点
2016/03/02 Javascript
javascript匀速动画和缓冲动画详解
2016/10/20 Javascript
bootstrap制作jsp页面(根据值让table显示选中)
2017/01/05 Javascript
ES6新特性之字符串的扩展实例分析
2017/04/01 Javascript
vue中如何让子组件修改父组件数据
2018/06/14 Javascript
jQuery事件模型默认行为执行顺序及trigger()与 triggerHandler()比较实例分析
2020/04/30 jQuery
JavaScript 实现自己的安卓手机自动化工具脚本(推荐)
2020/05/13 Javascript
javascript实现京东快递单号的查询效果
2020/11/30 Javascript
netbeans7安装python插件的方法图解
2013/12/24 Python
Python中字典映射类型的学习教程
2015/08/20 Python
pyqt5 QProgressBar清空进度条的实例
2019/06/21 Python
python自动化测试无法启动谷歌浏览器问题
2019/10/10 Python
tensorflow 重置/清除计算图的实现
2020/01/19 Python
python统计字符的个数代码实例
2020/02/07 Python
pyMySQL SQL语句传参问题,单个参数或多个参数说明
2020/06/06 Python
CSS3教程(7):CSS3嵌入字体
2009/04/02 HTML / CSS
Guess美国官网:美国知名服装品牌
2019/04/08 全球购物
单位工作证明范文
2014/09/14 职场文书
计划生育证明格式及范本
2014/10/09 职场文书
先进基层党组织事迹材料
2014/12/25 职场文书
学习保证书100字
2015/02/26 职场文书
鸦片战争观后感
2015/06/09 职场文书
2016年大学生寒假社会实践心得体会
2015/10/09 职场文书
python实现web邮箱扫描的示例(附源码)
2021/03/30 Python
数据库连接池
2021/04/06 MySQL
Go语言中的UTF-8实现
2021/04/26 Golang