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 相关文章推荐
jsvascript图像处理—(计算机视觉应用)图像金字塔
Jan 15 Javascript
jQuery对JSON数据进行排序输出的方法
Jun 24 Javascript
jQuery简单操作cookie的插件实例
Jan 13 Javascript
javascript函数自动执行常用方法汇总
Mar 28 Javascript
Javascript点击其他任意地方隐藏关闭DIV实例
Jun 21 Javascript
利用jquery实现验证输入的是否是数字、小数,包含保留几位小数
Dec 07 Javascript
JS限制条件补全问题实例分析
Dec 16 Javascript
easyui简介_动力节点Java学院整理
Jul 14 Javascript
Vue常用指令详解分析
Aug 19 Javascript
JavaScript常用工具函数大全
May 06 Javascript
详解Vue3 Teleport 的实践及原理
Dec 02 Vue.js
Vue ​v-model相关知识总结
Jan 28 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
图书管理程序(一)
2006/10/09 PHP
PHP性能优化 产生高度优化代码
2011/07/22 PHP
PHP 杂谈《重构-改善既有代码的设计》之三 重新组织数据
2012/04/09 PHP
PHP实现的带超时功能get_headers函数
2015/02/10 PHP
php实现多维数组中每个单元值(数字)翻倍的方法
2015/02/16 PHP
PHP实现多图上传(结合uploadify插件)思路分析
2016/11/30 PHP
PHP数组实际占用内存大小原理解析
2020/12/11 PHP
javascript 动态参数判空操作
2008/12/22 Javascript
javascript在事件监听方面的兼容性小结
2010/04/07 Javascript
jQuery 1.5.1 发布,全面支持IE9 修复大量bug
2011/02/26 Javascript
五段实用的js高级技巧
2011/12/20 Javascript
node.js中Socket.IO的进阶使用技巧
2014/11/04 Javascript
js实现浮动在网页右侧的简洁QQ在线客服代码
2015/09/04 Javascript
JS实现淡蓝色简洁竖向Tab点击切换效果
2015/10/06 Javascript
js实现下拉列表选中某个值的方法(3种方法)
2015/12/17 Javascript
PHP抓取HTTPS内容和错误处理的方法
2016/09/30 Javascript
解析JavaScript实现DDoS攻击原理与保护措施
2016/12/26 Javascript
Javascript中Promise的四种常用方法总结
2017/07/14 Javascript
Vue2.0父组件与子组件之间的事件发射与接收实例代码
2017/09/19 Javascript
微信小程序云开发之使用云存储
2019/05/17 Javascript
es6 super关键字的理解与应用实例分析
2020/02/15 Javascript
nuxt.js 在middleware(中间件)中实现路由鉴权操作
2020/11/06 Javascript
Python httplib,smtplib使用方法
2008/09/06 Python
Python实现3行代码解简单的一元一次方程
2014/08/18 Python
python通过邮件服务器端口发送邮件的方法
2015/04/30 Python
Python实现视频下载功能
2017/03/14 Python
python 拼接文件路径的方法
2018/10/23 Python
python3 selenium自动化测试 强大的CSS定位方法
2019/08/23 Python
详解如何用canvas画一个微笑的表情
2019/03/14 HTML / CSS
英国独特礼物想法和个性化礼物网站:notonthehighstreet.com
2018/04/16 全球购物
阳光体育:Sunny Sports(购买露营和远足设备)
2018/08/07 全球购物
MyHeritage美国:家族史研究和DNA测试的领先服务
2019/05/27 全球购物
2014年作风建设剖析材料
2014/10/23 职场文书
会计求职信怎么写
2015/03/20 职场文书
八年级英语教学反思
2016/02/15 职场文书
使用CSS实现百叶窗效果示例代码
2023/05/07 HTML / CSS