详解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 Jcrop插件实现图片选取功能
Nov 23 Javascript
document.createElement()用法及注意事项(ff下不兼容)
Mar 13 Javascript
让复选框只能选择一项的方法
Oct 08 Javascript
JQuery异步加载无限下拉框级联功能实现示例
Feb 19 Javascript
jQuery实现仿百度首页滑动伸缩展开的添加服务效果代码
Sep 09 Javascript
jquery点击缩略图切换视频播放特效代码分享
Sep 15 Javascript
详解JavaScript的变量和数据类型
Nov 27 Javascript
详谈innerHTML innerText的使用和区别
Aug 18 Javascript
axios发送post请求,提交图片类型表单数据方法
Mar 16 Javascript
vue中的inject学习教程
Apr 24 Javascript
vue实现从外部修改组件内部的变量的值
Jul 30 Javascript
Vue如何清空对象
Mar 03 Vue.js
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
php 的加密函数 md5,crypt,base64_encode 等使用介绍
2012/04/09 PHP
php中通过curl smtp发送邮件
2012/06/05 PHP
关于crontab的使用详解
2013/06/24 PHP
PHP实现判断数组是一维、二维或几维的方法
2017/02/06 PHP
PHP获取文本框、密码域、按钮的值实例代码
2017/04/19 PHP
jQuery+PHP实现图片上传并提交功能
2020/07/27 PHP
Prototype RegExp对象 学习
2009/07/19 Javascript
JavaScript 原型链学习总结
2010/10/29 Javascript
jQuery中wrapInner()方法用法实例
2015/01/16 Javascript
浅谈document.write()输出样式
2015/05/07 Javascript
javascript实现下雪效果【实例代码】
2016/05/03 Javascript
node-http-proxy修改响应结果实例代码
2016/06/06 Javascript
jQuery基于ID调用指定iframe页面内的方法
2016/07/06 Javascript
jQuery实现自动调用和触发某个事件的方法
2016/11/18 Javascript
bootstrap table 数据表格行内修改的实现代码
2017/02/13 Javascript
关于微信小程序获取小程序码并接受buffer流保存为图片的方法
2019/06/07 Javascript
Vuex的API文档说明详解
2020/02/05 Javascript
python进程类subprocess的一些操作方法例子
2014/11/22 Python
Python实现基于权重的随机数2种方法
2015/04/28 Python
python查看FTP是否能连接成功的方法
2015/07/30 Python
Python3的urllib.parse常用函数小结(urlencode,quote,quote_plus,unquote,unquote_plus等)
2016/09/18 Python
Python自动生产表情包
2017/03/17 Python
Python实现对百度云的文件上传(实例讲解)
2017/10/21 Python
python中numpy.zeros(np.zeros)的使用方法
2017/11/07 Python
Python PyQt4实现QQ抽屉效果
2018/04/20 Python
Python使用微信接入图灵机器人过程解析
2019/11/04 Python
django的模型类管理器——数据库操作的封装详解
2020/04/01 Python
python实现在内存中读写str和二进制数据代码
2020/04/24 Python
HTML5调用手机发短信和打电话功能
2020/04/29 HTML / CSS
科沃斯机器人官网商城:Ecovacs
2016/08/29 全球购物
澳大利亚儿童和婴儿产品在线商店:Lime Tree Kids
2017/10/05 全球购物
飞利浦美国官网:Philips美国
2020/02/28 全球购物
副董事长岗位职责
2014/04/02 职场文书
人事任命书格式
2014/06/05 职场文书
五一劳动节演讲稿
2014/09/12 职场文书
公司转让协议书
2016/03/19 职场文书