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同意等待代码实现心得
Jan 01 Javascript
JavaScript中创建类/对象的几种方法总结
Nov 29 Javascript
微信JSSDK上传图片
Aug 23 Javascript
原生javascript实现addClass,removeClass,hasClass函数
Feb 25 Javascript
Java遍历集合方法分析(实现原理、算法性能、适用场合)
Apr 25 Javascript
jQuery简单实现点击文本框复制内容到剪贴板上的方法
Aug 01 Javascript
jQuery实现简单的手风琴效果
Apr 17 jQuery
重新认识vue之事件阻止冒泡的实现
Aug 02 Javascript
JavaScript Array对象基本方法详解
Sep 03 Javascript
微信小程序实现图片翻转效果的实例代码
Sep 20 Javascript
vue组件开发之tab切换组件使用详解
Aug 21 Javascript
吃通javascript正则表达式
Apr 21 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 post大量数据时发现数据丢失问题解决方法
2015/06/20 PHP
php实现无限级分类(递归方法)
2015/08/06 PHP
Yii基于数组和对象的Model查询技巧实例详解
2015/12/28 PHP
YiiFramework入门知识点总结(图文教程)
2015/12/28 PHP
jquery+thinkphp实现跨域抓取数据的方法
2016/10/15 PHP
laravel实现分页样式替换示例代码(增加首、尾页)
2017/09/22 PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
2019/09/30 PHP
PHP常用函数之base64图片上传功能详解
2019/10/21 PHP
基于jquery的二级联动菜单实现代码
2011/04/25 Javascript
javascript实现左右控制无缝滚动
2014/12/31 Javascript
JavaScript模拟push
2016/03/06 Javascript
通过jquery-ui中的sortable来实现拖拽排序的简单实例
2016/05/24 Javascript
jQuery基于函数重载实现自定义Alert函数样式的方法
2016/07/27 Javascript
Javascript中arguments对象的详解与使用方法
2016/10/04 Javascript
Angular 开发学习之Angular CLI的安装使用
2017/12/31 Javascript
基于layui的table插件进行复选框联动功能的实现方法
2019/09/19 Javascript
redux处理异步action解决方案
2020/03/22 Javascript
vue中echarts图表大小适应窗口大小且不需要刷新案例
2020/07/19 Javascript
[06:38]DOTA2怒掀电竞风暴 2013Chinajoy
2013/07/27 DOTA
[53:52]OG vs EG 2018国际邀请赛淘汰赛BO3 第二场 8.23
2018/08/24 DOTA
Python基础语法(Python基础知识点)
2016/02/28 Python
Python环境搭建之OpenCV的步骤方法
2017/10/20 Python
wxPython+Matplotlib绘制折线图表
2019/11/19 Python
Python selenium文件上传下载功能代码实例
2020/04/13 Python
Speedo澳大利亚官网:全球领先游泳品牌
2018/02/04 全球购物
使用useBean标志初始化BEAN时如何接受初始化参数
2012/02/11 面试题
单位介绍信范文
2014/01/18 职场文书
周年庆典邀请函范文
2014/01/24 职场文书
摄影助理岗位职责
2014/02/07 职场文书
发展党员工作情况汇报
2014/10/28 职场文书
2014五年级班主任工作总结
2014/12/05 职场文书
2014办公室年度工作总结
2014/12/09 职场文书
党员倡议书
2015/01/19 职场文书
奇妙的 CSS shapes(CSS图形)
2021/04/05 HTML / CSS
pytorch 如何使用amp进行混合精度训练
2021/05/24 Python
Win11远程连接不上怎么办?Win11远程桌面用不了的解决方法
2022/08/05 数码科技