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 相关文章推荐
js 如何实现对数据库的增删改查
Nov 23 Javascript
document.documentElement的一些使用技巧
Apr 18 Javascript
前台js调用后台方法示例
Dec 02 Javascript
JS实现鼠标单击与双击事件共存
Mar 08 Javascript
jquery实现的鼠标拖动排序Li或Table
May 04 Javascript
JavaScript encodeURI 和encodeURIComponent
Dec 04 Javascript
微信小程序中顶部导航栏的实现代码
Mar 30 Javascript
jquery 键盘事件的使用方法详解
Sep 13 jQuery
微信小程序模板和模块化用法实例分析
Nov 28 Javascript
JavaScript基础心法 数据类型
Mar 05 Javascript
VUE+elementui面包屑实现动态路由详解
Nov 04 Javascript
JavaScript闭包原理与用法学习笔记
May 29 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
站长助手-网站web在线管理程序 v1.0 下载
2007/05/12 PHP
php守护进程 加linux命令nohup实现任务每秒执行一次
2011/07/04 PHP
PHP实现UTF-8文件BOM自动检测与移除实例
2014/11/05 PHP
yii2.0之GridView自定义按钮和链接用法
2014/12/15 PHP
PHP基于PDO调用sqlserver存储过程通用方法【基于Yii框架】
2017/10/07 PHP
php实现记事本案例
2020/10/20 PHP
JavaScript Event学习第八章 事件的顺序
2010/02/07 Javascript
php的文件上传入门教程(实例讲解)
2014/04/10 Javascript
JavaScript中的Truthy和Falsy介绍
2015/01/01 Javascript
Javascript中的几种URL编码方法比较
2015/01/23 Javascript
js仿黑客帝国字母掉落效果代码分享
2020/11/08 Javascript
js获取元素下的第一级子元素的方法(推荐)
2017/03/05 Javascript
Mongoose实现虚拟字段查询的方法详解
2017/08/15 Javascript
AngularJS实现的输入框字数限制提醒功能示例
2017/10/26 Javascript
React全家桶环境搭建过程详解
2018/05/18 Javascript
vue单页缓存方案分析及实现
2018/09/25 Javascript
记一次用vue做的活动页的方法步骤
2019/04/11 Javascript
webpack.DefinePlugin与cross-env区别详解
2020/02/23 Javascript
JS实现简单贪吃蛇小游戏
2020/10/28 Javascript
[01:02:30]Mineski vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第三场 8.22
2019/09/05 DOTA
python实现目录树生成示例
2014/03/28 Python
Python实现KNN(K-近邻)算法的示例代码
2019/03/05 Python
pycharm创建一个python包方法图解
2019/04/10 Python
Python实现的爬取百度贴吧图片功能完整示例
2019/05/10 Python
Python 使用type来定义类的实现
2019/11/19 Python
Selenium环境变量配置(火狐浏览器)及验证实现
2020/12/07 Python
解析html5 canvas实现背景鼠标连线动态效果代码
2019/06/17 HTML / CSS
高街生活方式全球在线商店:AZBRO
2017/08/26 全球购物
如何提高JDBC的性能
2013/04/30 面试题
岗位职责的构建方法
2014/02/01 职场文书
创先争优一句话承诺
2014/05/29 职场文书
2014年销售助理工作总结
2014/12/01 职场文书
幼儿园中班教师个人总结
2015/02/05 职场文书
刘公岛导游词
2015/02/05 职场文书
大学生求职自荐信范文
2015/03/04 职场文书
Ajax请求超时与网络异常处理图文详解
2021/05/23 Javascript