详解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实现的超出屏幕时把固定层变为定位层的代码
Feb 23 Javascript
jQuery避免$符和其他JS库冲突的方法对比
Feb 20 Javascript
实用框架(iframe)操作代码
Oct 23 Javascript
Javascript中数组sort和reverse用法分析
Dec 30 Javascript
jQuery实现鼠标滚轮动态改变样式或效果
Jan 05 Javascript
jQuery使用animate创建动画用法实例
Aug 07 Javascript
javascript实现下雪效果【实例代码】
May 03 Javascript
AngularJS中的Promise详细介绍及实例代码
Dec 13 Javascript
JS代码实现电脑配置检测功能
Mar 21 Javascript
微信小程序有旋转动画效果的音乐组件实例代码
Aug 22 Javascript
Angular6新特性之Angular Material
Dec 28 Javascript
jquery图片预览插件实现方法详解
Jul 18 jQuery
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
关于BIG5-HKSCS的解决方法
2007/03/20 PHP
深入Nginx + PHP 缓存详解
2013/07/11 PHP
PHP使用PDO连接ACCESS数据库
2015/03/05 PHP
php将12小时制转换成24小时制的方法
2015/03/31 PHP
mac系统下为 php 添加 pcntl 扩展
2016/08/28 PHP
PHP实现文件上传下载实例
2016/10/18 PHP
使用Javascript接收get传递的值的代码
2011/11/30 Javascript
非主流的textarea自增长实现js代码
2011/12/20 Javascript
jquery 自定义容器下雨效果可将下雨图标改为其他
2014/04/23 Javascript
JavaScript动态改变div属性的实现方法
2015/07/22 Javascript
jquery实现的淡入淡出下拉菜单效果
2015/08/25 Javascript
浅析javascript中的Event事件
2016/12/09 Javascript
BootStrap select2 动态改变值的方法
2017/02/10 Javascript
详解Vue.js 2.0 如何使用axios
2017/04/21 Javascript
关于angularJs清除浏览器缓存的方法
2017/11/28 Javascript
Bootstrap 模态框自定义点击和关闭事件详解
2018/08/10 Javascript
对vue2.0中.vue文件页面跳转之.$router.push的用法详解
2018/08/24 Javascript
JS字符串与二进制的相互转化实例代码详解
2019/06/28 Javascript
实例讲解JavaScript 计时事件
2020/07/04 Javascript
Python中用于转换字母为小写的lower()方法使用简介
2015/05/19 Python
Python开发之快速搭建自动回复微信公众号功能
2016/04/22 Python
关于Python面向对象编程的知识点总结
2017/02/14 Python
导入tensorflow:ImportError: libcublas.so.9.0 报错
2020/01/06 Python
python GUI库图形界面开发之PyQt5单选按钮控件QRadioButton详细使用方法与实例
2020/02/28 Python
Android Q之气泡弹窗的实现示例
2020/06/23 Python
英国排名第一的宠物店:PetPlanet
2020/02/02 全球购物
SK-II神仙水美国官网:SK-II美国
2020/02/25 全球购物
优秀研究生自我鉴定
2013/12/04 职场文书
个人培训自我鉴定
2014/03/28 职场文书
团结就是力量演讲稿
2014/05/21 职场文书
立志成才演讲稿
2014/09/04 职场文书
2014年房产经纪人工作总结
2014/12/08 职场文书
婚礼上证婚人致辞
2015/07/28 职场文书
任命书格式模板
2015/09/22 职场文书
《鲸》教学反思
2016/02/23 职场文书
工作总结之小学教师体育工作范文(3篇)
2019/10/07 职场文书