详解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 相关文章推荐
Jquery截取中文字符串的实现代码
Dec 22 Javascript
用JQuery模仿淘宝的图片放大镜显示效果
Sep 15 Javascript
Jquery实现点击按钮,连续地向textarea中添加值的实例代码
Mar 08 Javascript
Javascript Objects详解
Sep 04 Javascript
JS实现可点击展开与关闭的左侧广告代码
Sep 02 Javascript
javascript实现获取指定精度的上传文件的大小简单实例
Oct 25 Javascript
vue 通过下拉框组件学习vue中的父子通讯
Dec 19 Javascript
浅谈Vue2.0中v-for迭代语法的变化(key、index)
Mar 06 Javascript
Node.js+ELK日志规范的实现
May 23 Javascript
详解vue中的父子传值双向绑定及数据更新问题
Jun 13 Javascript
使用apifm-wxapi模块中的问题及解决方法
Aug 05 Javascript
微信小程序批量监听输入框对按钮样式进行控制的实现代码
Oct 12 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
使用Thinkphp框架开发移动端接口
2015/08/05 PHP
php parse_str() 函数的定义和用法
2016/05/23 PHP
Thinkphp 中 distinct 的用法解析
2016/12/14 PHP
游戏人文件夹程序 ver 3.0
2006/07/14 Javascript
JavaScript 参数中的数组展开 [译]
2012/09/21 Javascript
判断js中各种数据的类型方法之typeof与0bject.prototype.toString讲解
2013/11/07 Javascript
Jquery使用Firefox FireBug插件调试Ajax步骤讲解
2013/12/02 Javascript
IE6-8中Date不支持toISOString的修复方法
2014/05/04 Javascript
Javascript编程之继承实例汇总
2015/11/28 Javascript
js实现C#的StringBuilder效果完整实例
2015/12/22 Javascript
JS上传组件FileUpload自定义模板的使用方法
2016/05/10 Javascript
jQuery中的select操作详解
2016/11/29 Javascript
学习使用Bootstrap输入框、导航、分页等常用组件
2017/05/11 Javascript
JavaScript实现HTML导航栏下拉菜单
2020/11/25 Javascript
[53:38]OG vs LGD 2018国际邀请赛淘汰赛BO3 第三场 8.26
2018/08/30 DOTA
在Linux系统上通过uWSGI配置Nginx+Python环境的教程
2015/12/25 Python
PyQt5固定窗口大小的方法
2019/06/18 Python
解决pyqt5中QToolButton无法使用的问题
2019/06/21 Python
python opencv将图片转为灰度图的方法示例
2019/07/31 Python
python图形开发GUI库wxpython使用方法详解
2020/02/14 Python
基于python实现把json数据转换成Excel表格
2020/05/07 Python
利用Opencv实现图片的油画特效实例
2021/02/28 Python
前端隐藏出边界内容的实现方法
2016/04/14 HTML / CSS
CSS3色彩模式有哪些?CSS3 HSL色彩模式的定义
2016/04/26 HTML / CSS
iframe与window.onload如何使用详解
2020/05/07 HTML / CSS
德国家具在线:Fashion For Home
2017/03/11 全球购物
Desigual德国官网:在线购买原创服装
2018/03/27 全球购物
List、Map、Set三个接口,存取元素时,各有什么特点?
2015/09/27 面试题
外国人聘用意向书
2014/04/01 职场文书
反腐倡廉警示教育活动总结
2014/05/05 职场文书
运动会方阵口号
2014/06/07 职场文书
节水口号标语
2014/06/19 职场文书
2014年基建工作总结
2014/12/12 职场文书
接收函格式
2015/01/30 职场文书
大国崛起英国观后感
2015/06/02 职场文书
了解Redis常见应用场景
2021/06/23 Redis