详解ES6 系列之异步处理实战


Posted in Javascript onOctober 26, 2018

前言

我们以查找指定目录下的最大文件为例,感受从

回调函数 -> Promise -> Generator -> Async

异步处理方式的改变。

API 介绍

为了实现这个功能,我们需要用到几个 Nodejs 的 API,所以我们来简单介绍一下。

fs.readdir
readdir 方法用于读取目录,返回一个包含文件和目录的数组。

fs.stat
stat 方法的参数是一个文件或目录,它产生一个对象,该对象包含了该文件或目录的具体信息。此外,该对象还有一个 isFile() 方法可以判断正在处理的到底是一个文件,还是一个目录。

思路分析

我们基本的实现思路就是:

  • 用 fs.readdir 获取指定目录的内容信息
  • 循环遍历内容信息,使用 fs.stat 获取该文件或者目录的具体信息
  • 将具体信息储存起来
  • 当全部储存起来后,筛选其中的是文件的信息
  • 遍历比较,找出最大文件
  • 获取并返回最大文件

然后我们直接上代码吧。

回调函数

var fs = require('fs');
var path = require('path');

function findLargest(dir, cb) {
  // 读取目录下的所有文件
  fs.readdir(dir, function(er, files) {
    if (er) return cb(er);

    var counter = files.length;
    var errored = false;
    var stats = [];

    files.forEach(function(file, index) {
      // 读取文件信息
      fs.stat(path.join(dir, file), function(er, stat) {

        if (errored) return;

        if (er) {
          errored = true;
          return cb(er);
        }

        stats[index] = stat;

        // 事先算好有多少个文件,读完 1 个文件信息,计数减 1,当为 0 时,说明读取完毕,此时执行最终的比较操作
        if (--counter == 0) {

          var largest = stats
            .filter(function(stat) { return stat.isFile() })
            .reduce(function(prev, next) {
              if (prev.size > next.size) return prev
              return next
            })

          cb(null, files[stats.indexOf(largest)])
        }
      })
    })
  })
}

使用方式为:

// 查找当前目录最大的文件
findLargest('./', function(er, filename) {
  if (er) return console.error(er)
  console.log('largest file was:', filename)
});
Promise
var fs = require('fs');
var path = require('path');

var readDir = function(dir) {
  return new Promise(function(resolve, reject) {
    fs.readdir(dir, function(err, files) {
      if (err) reject(err);
      resolve(files)
    })
  })
}

var stat = function(path) {
  return new Promise(function(resolve, reject) {
    fs.stat(path, function(err, stat) {
      if (err) reject(err)
      resolve(stat)
    })
  })
}

function findLargest(dir) {
  return readDir(dir)
    .then(function(files) {
      let promises = files.map(file => stat(path.join(dir, file)))
      return Promise.all(promises).then(function(stats) {
        return { stats, files }
      })
    })
    .then(data => {

      let largest = data.stats
        .filter(function(stat) { return stat.isFile() })
        .reduce((prev, next) => {
          if (prev.size > next.size) return prev
          return next
        })

      return data.files[data.stats.indexOf(largest)]
    })

}

使用方式为:

findLargest('./')
.then(function(filename) {
  console.log('largest file was:', filename);
})
.catch(function() {
  console.log(error);
});
Generator
var fs = require('fs');
var path = require('path');

var co = require('co')

var readDir = function(dir) {
  return new Promise(function(resolve, reject) {
    fs.readdir(dir, function(err, files) {
      if (err) reject(err);
      resolve(files)
    })
  })
}

var stat = function(path) {
  return new Promise(function(resolve, reject) {
    fs.stat(path, function(err, stat) {
      if (err) reject(err)
      resolve(stat)
    })
  })
}

function* findLargest(dir) {
  var files = yield readDir(dir);
  var stats = yield files.map(function(file) {
    return stat(path.join(dir, file))
  })

  let largest = stats
    .filter(function(stat) { return stat.isFile() })
    .reduce((prev, next) => {
      if (prev.size > next.size) return prev
      return next
    })

  return files[stats.indexOf(largest)]

}

使用方式为:

co(findLargest, './')
.then(function(filename) {
  console.log('largest file was:', filename);
})
.catch(function() {
  console.log(error);
});
Async
var fs = require('fs');
var path = require('path');

var readDir = function(dir) {
  return new Promise(function(resolve, reject) {
    fs.readdir(dir, function(err, files) {
      if (err) reject(err);
      resolve(files)
    })
  })
}

var stat = function(path) {
  return new Promise(function(resolve, reject) {
    fs.stat(path, function(err, stat) {
      if (err) reject(err)
      resolve(stat)
    })
  })
}

async function findLargest(dir) {
  var files = await readDir(dir);

  let promises = files.map(file => stat(path.join(dir, file)))
  var stats = await Promise.all(promises)

  let largest = stats
    .filter(function(stat) { return stat.isFile() })
    .reduce((prev, next) => {
      if (prev.size > next.size) return prev
      return next
    })

  return files[stats.indexOf(largest)]

}

使用方式为:

findLargest('./')
.then(function(filename) {
  console.log('largest file was:', filename);
})
.catch(function() {
  console.log(error);
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript实现轮显新闻标题链接
Aug 13 Javascript
封装好的一个万能检测表单的方法
Jan 21 Javascript
Bootstrap教程JS插件弹出框学习笔记分享
May 17 Javascript
微信小程序 Nginx环境配置详细介绍
Feb 14 Javascript
javascript设计模式之单体模式学习笔记
Feb 15 Javascript
Angular2 父子组件数据通信实例
Jun 22 Javascript
Vue组件开发技巧总结
Mar 04 Javascript
vue 界面刷新数据被清除 localStorage的使用详解
Sep 16 Javascript
javascript定时器的简单应用示例【控制方块移动】
Jun 17 Javascript
Javascript异步编程async实现过程详解
Apr 02 Javascript
通过实例解析vuejs如何实现调试代码
Jul 16 Javascript
小程序实现上下切换位置
Nov 16 Javascript
element-ui 的el-button组件中添加自定义颜色和图标的实现方法
Oct 26 #Javascript
angularjs通过过滤器返回超链接的方法
Oct 26 #Javascript
js使用formData实现批量上传
Mar 27 #Javascript
详解webpack打包时排除其中一个css、js文件或单独打包一个css、js文件(两种方法)
Oct 26 #Javascript
js自定义input文件上传样式
Oct 26 #Javascript
解决axios会发送两次请求,有个OPTIONS请求的问题
Oct 25 #Javascript
在Vue中使用axios请求拦截的实现方法
Oct 25 #Javascript
You might like
《雄兵连》《烈阳天道》真的来了
2020/07/13 国漫
PHP常用函数小技巧
2008/09/11 PHP
php中使用$_REQUEST需要注意的一个问题
2013/05/02 PHP
PHP使用Mysql事务实例解析
2014/09/08 PHP
php随机生成数字字母组合的方法
2015/03/18 PHP
在php中设置session用memcache来存储的方法总结
2016/01/14 PHP
thinkPHP框架对接支付宝即时到账接口回调操作示例
2016/11/14 PHP
PHP如何防止XSS攻击与XSS攻击原理的讲解
2019/03/22 PHP
浅谈laravel 5.6 安装 windows上使用composer的安装过程
2019/10/18 PHP
刷新页面的几种方法小结(JS,ASP.NET)
2014/01/07 Javascript
禁止页面刷新让F5快捷键及右键都无效
2014/01/22 Javascript
JS获取文件大小方法小结
2015/12/08 Javascript
JS与HTML结合使用marquee标签实现无缝滚动效果代码
2016/07/05 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
2016/09/17 Javascript
JQ图片文件上传之前预览功能的简单实例(分享)
2017/11/12 Javascript
webpack引入eslint配置详解
2018/01/22 Javascript
Bootstrap 模态框自定义点击和关闭事件详解
2018/08/10 Javascript
React中使用外部样式的3种方式(小结)
2019/05/28 Javascript
layui table 表格上添加日期控件的两种方法
2019/09/28 Javascript
JavaScript常用8种数组去重代码实例
2020/09/09 Javascript
介绍Python的Django框架中的静态资源管理器django-pipeline
2015/04/25 Python
Python使用Turtle模块绘制五星红旗代码示例
2017/12/11 Python
Python面向对象基础入门之编码细节与注意事项
2018/12/11 Python
Python3 执行系统命令并获取实时回显功能
2019/07/09 Python
python3.x提取中文的正则表达式示例代码
2019/07/23 Python
Pytorch修改ResNet模型全连接层进行直接训练实例
2019/09/10 Python
python代码打印100-999之间的回文数示例
2019/11/24 Python
Python如何使用27行代码绘制星星图
2020/07/20 Python
Pytorch模型迁移和迁移学习,导入部分模型参数的操作
2021/03/03 Python
使用CSS3实现input多选框自定义样式的方法示例
2019/07/19 HTML / CSS
英国和国际包裹递送:ParcelCompare
2019/08/26 全球购物
线程同步的方法
2016/11/23 面试题
毕业自我评价
2014/02/05 职场文书
出售房屋委托书范本
2014/09/24 职场文书
品质保证书格式
2015/02/28 职场文书
Windows Server 2019 配置远程控制以及管理方法
2022/04/28 Servers