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 相关文章推荐
另类调用flash无须激活的方法
Dec 27 Javascript
《JavaScript高级程序设计》阅读笔记(三) ECMAScript中的引用类型
Feb 27 Javascript
网站如何做到完全不需要jQuery也可以满足简单需求
Jun 27 Javascript
Javascript基础教程之JavaScript语法
Jan 18 Javascript
jquery悬浮提示框完整实例
Jan 13 Javascript
JavaScript中的this,call,apply使用及区别详解
Jan 29 Javascript
jquery计算出left和top,让一个div水平垂直居中的简单实例
Jul 13 Javascript
移动端翻页插件dropload.js(支持Zepto和jQuery)
Jul 27 Javascript
超简单的Vue.js环境搭建教程
Mar 17 Javascript
Angular2 自定义validators的实现方法
Jul 05 Javascript
webpack实现热加载自动刷新的方法
Jul 30 Javascript
微信小程序实现搜索功能并跳转搜索结果页面
May 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
Windows下PHP的任意文件执行漏洞
2006/10/09 PHP
php 判断访客是否为搜索引擎蜘蛛的函数代码
2011/07/29 PHP
php类声明和php类使用方法示例分享
2014/03/29 PHP
php中的单引号、双引号和转义字符详解
2017/02/16 PHP
PHP实现双链表删除与插入节点的方法示例
2017/11/11 PHP
PHP扩展类型及安装方式解析
2020/04/27 PHP
Javascript miscellanea -display data real time, using window.status
2007/01/09 Javascript
通过JS 获取Mouse Position(鼠标坐标)的代码
2009/09/21 Javascript
js原生态函数中使用jQuery中的 $(this)无效的解决方法
2011/05/25 Javascript
关于图片的预加载过程中隐藏未知的
2012/12/19 Javascript
node.js中使用socket.io制作命名空间
2014/12/15 Javascript
ECMAScript 5中的属性描述符详解
2015/03/02 Javascript
深入理解bootstrap框架之第二章整体架构
2016/10/09 Javascript
JavaScript触发onScroll事件的函数节流详解
2016/12/14 Javascript
vue-cli如何快速构建vue项目
2017/04/26 Javascript
微信小程序 选项卡的简单实例
2017/05/24 Javascript
vue+mockjs模拟数据实现前后端分离开发的实例代码
2017/08/08 Javascript
浅谈jquery中ajax跨域提交的时候会有2次请求的问题
2017/11/10 jQuery
Express之托管静态文件的方法
2018/06/01 Javascript
微信小程序上传图片并等比列压缩到指定大小的实例代码
2019/10/24 Javascript
在 Vue 中编写 SVG 图标组件的方法
2020/02/24 Javascript
Vertx基于EventBus发送接受自定义对象
2020/11/16 Javascript
对python中xlsx,csv以及json文件的相互转化方法详解
2018/12/25 Python
浅谈python标准库--functools.partial
2019/03/13 Python
Django中modelform组件实例用法总结
2020/02/10 Python
香港个人化生活购物网站:Ballyhoo Limited
2016/09/10 全球购物
洛杉矶健身中心女性专用运动服饰品牌:Marika
2018/05/09 全球购物
师范应届生求职信
2013/11/15 职场文书
道路建设实施方案
2014/03/18 职场文书
尊老爱幼演讲稿
2014/09/04 职场文书
2014年9.18纪念日演讲稿
2014/09/14 职场文书
2015年度内部审计工作总结
2015/05/20 职场文书
盗窃案辩护词
2015/05/21 职场文书
SpringRetry重试框架的具体使用
2021/07/25 Java/Android
Java8 Stream API 提供了一种高效且易于使用的处理数据的方式
2022/04/13 Java/Android
MySql按时,天,周,月进行数据统计
2022/08/14 MySQL