详解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 相关文章推荐
自用js开发框架小成 学习js的朋友可以看看
Nov 16 Javascript
基于jquery的用鼠标画出可移动的div
Sep 06 Javascript
jquery获取tr并更改tr内容示例代码
Feb 13 Javascript
JS实现自适应高度表单文本框的方法
Feb 25 Javascript
JavaScript实现的多个图片广告交替显示效果代码
Sep 04 Javascript
jQuery简单实现点击文本框复制内容到剪贴板上的方法
Aug 01 Javascript
JS实现数组去重,显示重复元素及个数的方法示例
Jan 21 Javascript
js打开word文档预览操作示例【不是下载】
May 23 Javascript
Vue实现按钮级权限方案
Nov 21 Javascript
基于aotu.js实现微信自动添加通讯录中的联系人功能
May 28 Javascript
前端JS获取URL参数的4种方法总结
Apr 05 Javascript
JS轻量级函数式编程实现XDM二
Jun 16 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的volist标签嵌套循环使用教程
2014/07/08 PHP
分享一段PHP制作的中文拼音首字母工具类
2014/12/11 PHP
php实现字符串首字母转换成大写的方法
2015/03/17 PHP
php中preg_match的isU代表什么意思
2015/10/01 PHP
YII CLinkPager分页类扩展增加显示共多少页
2016/01/29 PHP
php轻松实现文件上传功能
2016/03/03 PHP
php中目录操作opendir()、readdir()及scandir()用法示例
2019/06/08 PHP
如何获取JQUERY AJAX返回的JSON结果集实现代码
2012/12/10 Javascript
js获取height和width的方法说明
2013/01/06 Javascript
JS实现标签页效果(配合css)
2013/04/03 Javascript
js获得页面的高度和宽度的方法
2014/02/23 Javascript
简介JavaScript中POSITIVE_INFINITY值的使用
2015/06/05 Javascript
基于jQuery实现的菜单切换效果
2015/10/16 Javascript
JavaScript 控制字体大小设置的方法
2016/11/23 Javascript
bootstrap table动态加载数据示例代码
2017/03/25 Javascript
对象不支持indexOf属性或方法的解决方法(必看)
2017/05/28 Javascript
ng-events类似ionic中Events的angular全局事件
2018/09/05 Javascript
关于element的表单组件整理笔记
2021/02/05 Javascript
[01:14]3.19DOTA2发布会 三代刀塔人第二代
2014/03/25 DOTA
在Python中用keys()方法返回字典键的教程
2015/05/21 Python
Python解决抛小球问题 求小球下落经历的距离之和示例
2018/02/01 Python
用pandas按列合并两个文件的实例
2018/04/12 Python
python自制包并用pip免提交到pypi仅安装到本机【推荐】
2019/06/03 Python
Python解析json时提示“string indices must be integers”问题解决方法
2019/07/31 Python
pytorch 移动端部署之helloworld的使用
2020/10/30 Python
使用CSS3制作饼状旋转载入效果的实例
2015/06/23 HTML / CSS
北美女性服装零售连锁店:maurices
2019/06/12 全球购物
运动会解说词50字
2014/01/18 职场文书
《狮子和兔子》教学反思
2014/03/02 职场文书
学校献爱心活动总结
2014/07/08 职场文书
少先队工作总结2015
2015/05/13 职场文书
故意杀人罪辩护词
2015/05/21 职场文书
红色经典电影观后感
2015/06/18 职场文书
windows下快速安装nginx并配置开机自启动的方法
2021/05/11 Servers
Pytorch 统计模型参数量的操作 param.numel()
2021/05/13 Python
Django框架模板用法详解
2022/06/10 Python