详解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 相关文章推荐
ArrayList类(增强版)
Apr 04 Javascript
用Javscript实现表单复选框的全选功能
May 25 Javascript
boxy基于jquery的弹出层对话框插件扩展应用 弹出层选择器
Nov 21 Javascript
Javascript Memoizer浅析
Oct 16 Javascript
JavaScript实现简单获取当前网页网址的方法
Nov 09 Javascript
深入浅析JavaScript的API设计原则
Jun 14 Javascript
Vue.js仿Metronic高级表格(二)数据渲染
Apr 19 Javascript
微信小程序 滚动到某个位置添加class效果实现代码
Apr 19 Javascript
浅谈Node.js ORM框架Sequlize之表间关系
Jul 24 Javascript
Angular使用 ng-img-max 调整浏览器中的图片的示例代码
Aug 17 Javascript
JavaScript实现数字前补“0”的五种方法示例
Jan 03 Javascript
js实现烟花特效
Mar 02 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
虹吸壶煮咖啡26个注意事项
2021/03/03 冲泡冲煮
PHP5中MVC结构学习
2006/10/09 PHP
火车头discuz6.1 完美采集的php接口文件
2009/09/13 PHP
php实现简单的MVC框架实例
2015/09/23 PHP
PHP基于IMAP收取邮件的方法示例
2017/08/07 PHP
PHP 进度条函数的简单实例
2017/09/19 PHP
php删除一个路径下的所有文件夹和文件的方法
2018/02/07 PHP
一实用的实现table排序的Javascript类库
2007/09/12 Javascript
用JQuery 实现AJAX加载XML并解析的脚本
2009/07/25 Javascript
JS+XML 省份和城市之间的联动实现代码
2009/10/14 Javascript
AJAX使用了UpdatePanel后无法使用alert弹出脚本
2010/04/02 Javascript
jquery蒙版控件实现代码
2010/12/08 Javascript
jquery.post用法示例代码
2014/01/03 Javascript
10分钟学会写Jquery插件实例教程
2014/09/06 Javascript
nodejs学习笔记之路由
2017/03/27 NodeJs
vue mint-ui学习笔记之picker的使用
2017/10/11 Javascript
vue如何将v-for中的表格导出来
2018/05/07 Javascript
关于IDEA中的.VUE文件报错 Export declarations are not supported by current JavaScript version
2020/10/17 Javascript
解决Antd Table表头加Icon和气泡提示的坑
2020/11/17 Javascript
vite2.0+vue3移动端项目实战详解
2021/03/03 Vue.js
使用python BeautifulSoup库抓取58手机维修信息
2013/11/21 Python
Python实现Youku视频批量下载功能
2017/03/14 Python
python验证码识别教程之灰度处理、二值化、降噪与tesserocr识别
2018/06/04 Python
PyQt5 closeEvent关闭事件退出提示框原理解析
2020/01/08 Python
Python 通过正则表达式快速获取电影的下载地址
2020/08/17 Python
Django框架安装及项目创建过程解析
2020/09/14 Python
解决python3.6用cx_Oracle库连接Oracle的问题
2020/12/07 Python
python 统计list中各个元素出现的次数的几种方法
2021/02/20 Python
英国购买威士忌网站:Master of Malt
2019/09/26 全球购物
土木工程专业自荐信
2013/10/04 职场文书
初中语文教学反思
2014/02/02 职场文书
店长职务说明书
2014/02/04 职场文书
2014年双拥工作总结
2014/11/21 职场文书
聚会通知怎么写
2015/04/23 职场文书
毕业实习感受与体会
2015/05/26 职场文书
python如何在word中存储本地图片
2021/04/07 Python