详解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 Eval 函数使用
Mar 23 Javascript
再说AutoComplete自动补全之实现原理
Nov 05 Javascript
jQuery Ajax异步处理Json数据详解
Nov 05 Javascript
javascript面向对象程序设计(一)
Jan 29 Javascript
JavaScript中数组继承的简单示例
Jul 29 Javascript
js获取图片宽高的方法
Nov 25 Javascript
Javascript实现图片不间断滚动的代码
Jun 22 Javascript
AngularJS在IE下取数据总是缓存问题的解决方法
Aug 05 Javascript
JavaScript中清空数组的方法总结
Dec 02 Javascript
非常优秀的JS图片轮播插件Swiper的用法
Jan 03 Javascript
判断div滑动到底部的scroll实例代码
Nov 15 Javascript
node使用async_hooks模块进行请求追踪
Jan 28 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
模拟OICQ的实现思路和核心程序(二)
2006/10/09 PHP
mysql 的 like 问题,超强毕杀记!!!
2007/01/18 PHP
9个经典的PHP代码片段分享
2014/12/18 PHP
PHP连接MySQL数据的操作要点
2015/03/20 PHP
PHP的Yii框架使用中的一些错误解决方法与建议
2015/08/21 PHP
yii2.0数据库迁移教程【多个数据库同时同步数据】
2016/10/08 PHP
详解PHP安装mysql.so扩展的方法
2016/12/31 PHP
JavaScript 继承详解(三)
2009/07/13 Javascript
Javascript 面向对象编程(coolshell)
2012/03/18 Javascript
增强用户体验友好性之jquery easyui window 窗口关闭时的提示
2012/06/22 Javascript
JS解决url传值出现中文乱码的另类办法
2013/04/08 Javascript
js点击button按钮跳转到另一个新页面
2014/10/10 Javascript
jquery通过closest选择器修改上级元素的方法
2015/03/17 Javascript
jQuery实现模拟marquee标签效果
2015/07/14 Javascript
基于JavaScript实现购物网站商品放大镜效果
2016/09/06 Javascript
Angular2学习笔记——详解路由器模型(Router)
2016/12/02 Javascript
非常优秀的JS图片轮播插件Swiper的用法
2017/01/03 Javascript
微信小程序 轮播图swiper详解及实例(源码下载)
2017/01/11 Javascript
Javascript中的prototype与继承
2017/02/06 Javascript
利用nvm管理多个版本的node.js与npm详解
2017/11/02 Javascript
vue2.0 datepicker使用方法
2018/02/04 Javascript
解决iView中时间控件选择的时间总是少一天的问题
2018/03/15 Javascript
vue2.0中set添加属性后视图不能更新的解决办法
2019/02/22 Javascript
vue+iview动态渲染表格详解
2019/03/19 Javascript
Vue可自定义tab组件用法实例
2019/10/24 Javascript
基于javascript实现碰撞检测
2020/03/12 Javascript
python3.6+opencv3.4实现鼠标交互查看图片像素
2018/02/26 Python
pycharm重置设置,恢复默认设置的方法
2018/10/22 Python
对pyqt5之menu和action的使用详解
2019/06/20 Python
使用python制作游戏下载进度条的代码(程序说明见注释)
2019/10/24 Python
详解如何用canvas画一个微笑的表情
2019/03/14 HTML / CSS
韩国著名的在线综合购物网站:Akmall
2016/08/07 全球购物
小学生作文评语
2014/04/18 职场文书
辞职信范文大全
2015/03/02 职场文书
酒店圣诞节活动总结
2015/05/06 职场文书
Android超详细讲解组件ScrollView的使用
2022/03/31 Java/Android