详解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 ready函数、css函数及text()使用示例
Sep 27 Javascript
封装的jquery翻页滚动(示例代码)
Nov 18 Javascript
简介JavaScript中的setTime()方法的使用
Jun 11 Javascript
实现一个简单的vue无限加载指令方法
Jan 10 Javascript
jquery Form轻松实现文件上传
May 24 jQuery
Vue自定义指令使用方法详解
Aug 21 Javascript
jQuery实现的监听导航滚动置顶状态功能示例
Jul 23 jQuery
koa2使用ejs和nunjucks作为模板引擎的使用
Nov 27 Javascript
JS匿名函数内部this指向问题详析
May 10 Javascript
vue中实现拖动调整左右两侧div的宽度的示例代码
Jul 22 Javascript
vue+iview框架实现左侧动态菜单功能的示例代码
Jul 23 Javascript
vue+Element-ui实现分页效果
Nov 15 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
PHP5 面向对象程序设计
2008/02/13 PHP
php批量更改数据库表前缀实现方法
2013/10/26 PHP
ThinkPHP控制器里javascript代码不能执行的解决方法
2014/11/22 PHP
thinkphp的URL路由规则与配置实例
2014/11/26 PHP
PHP获取photoshop写入图片文字信息的方法
2015/03/31 PHP
php实现微信公众平台账号自定义菜单类
2015/10/11 PHP
在Laravel 中实现是否关注的示例
2019/10/22 PHP
php实现将数组或对象写入到文件的方法小结【三种方法】
2020/04/22 PHP
IE 下的只读 innerHTML
2009/08/21 Javascript
javascript工具库代码
2012/03/29 Javascript
给页面渲染时间加速 干掉Dom Level 0 Event
2012/12/19 Javascript
js批量设置样式的三种方法不推荐使用with
2013/02/25 Javascript
jquery实现带复选框的表格行选中删除时高亮显示
2013/08/01 Javascript
判断客户浏览器是否支持cookie的示例代码
2013/12/23 Javascript
jQuery焦点图切换特效代码分享
2015/09/15 Javascript
学习Javascript面向对象编程之封装
2016/02/23 Javascript
Bootstrap基本组件学习笔记之列表组(11)
2016/12/07 Javascript
Bootstrap3 多选和单选框(checkbox)
2016/12/29 Javascript
ionic实现底部分享功能
2017/05/11 Javascript
JavaScript实现多重继承的方法分析
2018/01/09 Javascript
JQuery元素快速查找与操作
2018/04/22 jQuery
jQuery pagination分页示例详解
2018/10/23 jQuery
小程序实现列表多个批量倒计时
2021/01/29 Javascript
vue v-for 使用问题整理小结
2019/08/04 Javascript
JavaScript编写开发动态时钟
2020/07/29 Javascript
[01:05:12]2014 DOTA2国际邀请赛中国区预选赛 TongFu VS CIS-GAME
2014/05/21 DOTA
python实现的简单RPG游戏流程实例
2015/06/28 Python
在Python中如何传递任意数量的实参的示例代码
2019/03/21 Python
ASP.NET Core中的配置详解
2021/02/05 Python
HTML5 Canvas图像模糊完美解决办法
2018/02/06 HTML / CSS
印度尼西亚最好的小工具在线商店:Erafone.com
2019/03/26 全球购物
会计应聘求职信范文
2013/12/17 职场文书
大学毕业感言100字
2014/02/03 职场文书
投资建议书模板
2014/05/12 职场文书
驻村工作先进事迹
2014/08/14 职场文书
女儿满月酒致辞
2015/07/29 职场文书