详解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 使用手册(六)
Sep 23 Javascript
Javascript级联下拉菜单以及AJAX数据验证核心代码
May 10 Javascript
jquery下div 的resize事件示例代码
Mar 09 Javascript
Egret引擎开发指南之视觉编程
Sep 03 Javascript
JavaScript参数个数可变的函数举例说明
Oct 10 Javascript
jQuery $命名冲突解决方案汇总
Nov 13 Javascript
编写高质量JavaScript代码的基本要点
Mar 02 Javascript
修改 bootstrap table 默认detailRow样式的实例代码
Jul 21 Javascript
JavaScript面向对象的程序设计(犯迷糊的小羊)
May 27 Javascript
Vue2.0仿饿了么webapp单页面应用详细步骤
Jul 08 Javascript
浅谈Node 异步IO和事件循环
May 05 Javascript
微信小程序向Java后台传输参数的方法实现
Dec 10 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
山进SANGEAN ATS-909X电路分析
2021/03/02 无线电
PHP安装攻略:常见问题解答(一)
2006/10/09 PHP
兼容PHP5的PHP目录管理函数库
2008/07/10 PHP
php 引用(&)详解
2009/11/20 PHP
php中将时间差转换为字符串提示的实现代码
2011/08/08 PHP
关于PHP二进制流 逐bit的低位在前算法(详解)
2013/06/13 PHP
PHP调用C#开发的dll类库方法
2014/07/28 PHP
JS 面向对象之神奇的prototype
2011/02/26 Javascript
jquery不会自动回收xmlHttpRequest对象 导致了内存溢出
2012/06/18 Javascript
用js调用迅雷下载代码的二种方法
2013/04/15 Javascript
理解jQuery stop()方法
2014/11/21 Javascript
js实现表单Radio切换效果的方法
2015/08/17 Javascript
关于js函数解释(包括内嵌,对象等)
2016/11/20 Javascript
Angular2 父子组件数据通信实例
2017/06/22 Javascript
webpack实现一个行内样式px转vw的loader示例
2018/09/13 Javascript
详解js创建对象的几种方法及继承
2019/04/12 Javascript
小程序如何构建骨架屏
2019/05/29 Javascript
js实现表格单列按字母排序
2020/08/12 Javascript
通过高德地图API获得某条道路上的所有坐标用于描绘道路的方法
2020/08/24 Javascript
微信小程序用户登录和登录态维护的实现
2020/12/10 Javascript
python基础教程之Hello World!
2014/08/29 Python
Python实现动态加载模块、类、函数的方法分析
2017/07/18 Python
Python实现统计英文文章词频的方法分析
2019/01/28 Python
Django CBV类的用法详解
2019/07/26 Python
python实现把两个二维array叠加成三维array示例
2019/11/29 Python
moosejaw旗下的户外商品促销网站:Mountain Steals
2017/02/27 全球购物
TripAdvisor土耳其网站:全球知名旅行社区,真实旅客评论
2017/04/17 全球购物
Get The Label中文官网:英国运动时尚购物平台
2017/04/19 全球购物
伊芙丽官方旗舰店:中国淑女一线品牌
2017/12/01 全球购物
德国家用电器购物网站:Premiumshop24
2019/08/22 全球购物
毕业实习计划书
2015/01/16 职场文书
2015年办公室工作总结范文
2015/03/31 职场文书
房租涨价通知
2015/04/23 职场文书
军训阅兵新闻稿
2015/07/17 职场文书
MySQL深度分页(千万级数据量如何快速分页)
2021/07/25 MySQL
TS 类型兼容教程示例详解
2022/09/23 Javascript