详解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 相关文章推荐
[IE&FireFox兼容]JS对select操作
Jan 07 Javascript
jquery给图片添加鼠标经过时的边框效果
Nov 12 Javascript
AngularJS 遇到的小坑与技巧小结
Jun 07 Javascript
jQuery基于ajax方式实现用户名存在性检查功能示例
Feb 10 Javascript
JS获取浮动(float)元素的style.left值为空的快速解决办法
Feb 19 Javascript
设置cookie指定时间失效(实例代码)
May 28 Javascript
解决ie img标签内存泄漏的问题
Oct 13 Javascript
解决Vue中引入swiper,在数据渲染的时候,发生不滑动的问题
Sep 27 Javascript
微信小程序人脸识别功能代码实例
May 07 Javascript
js获取图片的base64编码并压缩
Dec 05 Javascript
React中使用Vditor自定义图片详解
Dec 25 Javascript
vue特效之翻牌动画
Apr 20 Vue.js
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
Email+URL的判断和自动转换函数
2006/10/09 PHP
dedecms后台验证码总提示错误的解决方法
2007/03/21 PHP
php str_pad 函数使用详解
2009/01/13 PHP
php绘制一个扇形的方法
2015/01/24 PHP
PHP微信PC二维码登陆的实现思路
2017/07/13 PHP
基于jquery tab切换(防止页面刷新)
2012/05/23 Javascript
js汉字转拼音实现代码
2013/02/06 Javascript
JQuery弹出炫丽对话框的同时让背景变灰色
2014/05/22 Javascript
js实现右下角提示框的方法
2015/02/03 Javascript
JavaScript中exec函数用法实例分析
2015/06/08 Javascript
使用struts2+Ajax+jquery验证用户名是否已被注册
2016/03/22 Javascript
JavaScript中0和""比较引发的问题
2016/05/26 Javascript
Vue.js学习记录之在元素与template中使用v-if指令实例
2017/06/27 Javascript
Vue组件之Tooltip的示例代码
2017/10/18 Javascript
对layui中表单元素的使用详解
2018/08/15 Javascript
vue、react等单页面项目部署到服务器的方法及vue和react的区别
2018/09/29 Javascript
[09:34]2018DOTA2国际邀请赛寻真——永不放弃的iG
2018/08/14 DOTA
python生成词云的实现方法(推荐)
2017/06/13 Python
详解 Python 与文件对象共事的实例
2017/09/11 Python
Python使用arrow库优雅地处理时间数据详解
2017/10/10 Python
python实现任意位置文件分割的实例
2018/12/14 Python
Django model 中设置联合约束和联合索引的方法
2019/08/06 Python
详解python中index()、find()方法
2019/08/29 Python
QML用PathView实现轮播图
2020/06/03 Python
可视化pytorch 模型中不同BN层的running mean曲线实例
2020/06/24 Python
PyQt5的相对布局管理的实现
2020/08/07 Python
利用CSS的Sass预处理器(框架)来制作居中效果
2016/03/10 HTML / CSS
使用 css3 transform 属性来变换背景图的方法
2019/05/07 HTML / CSS
Silk Therapeutics官网:清洁、抗衰老护肤品
2020/08/12 全球购物
内部类的定义、种类以及优点
2013/10/16 面试题
旅游管理专业生自荐信范文
2014/01/02 职场文书
个人现实表现材料
2014/02/04 职场文书
设计大赛策划方案
2014/06/13 职场文书
四风问题班子对照检查材料
2014/09/27 职场文书
2015年个人思想总结
2015/03/09 职场文书
机修车间主任岗位职责
2015/04/08 职场文书