详解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 相关文章推荐
javascript showModalDialog 多层模态窗口实现页面提交及刷新的代码
Nov 28 Javascript
jQuery 学习第七课 扩展jQuery的功能 插件开发
May 17 Javascript
Javascript创建Silverlight Plugin以及自定义nonSilverlight和lowSilverlight样式
Jun 28 Javascript
jQuery源码分析之jQuery.fn.each与jQuery.each用法
Jan 23 Javascript
JavaScript动态创建div等元素实例讲解
Jan 06 Javascript
js 性能优化之算法和流程控制
Feb 15 Javascript
JavaScript表单验证实现代码
May 22 Javascript
详解vue中引入stylus及报错解决方法
Sep 22 Javascript
Vue绑定内联样式问题
Oct 17 Javascript
VUE-cli3使用 svg-sprite-loader
Oct 20 Javascript
vue+vant-UI框架实现购物车的复选框全选和反选功能
Nov 05 Javascript
JavaScript 双向链表操作实例分析【创建、增加、查找、删除等】
Apr 28 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
10个超级有用值得收藏的PHP代码片段
2015/01/22 PHP
php 使用curl模拟登录人人(校内)网的简单实例
2016/06/06 PHP
如何在centos8自定义目录安装php7.3
2019/11/28 PHP
多浏览器兼容的获取元素和鼠标的位置的js代码
2009/12/15 Javascript
多个表单中如何获得这个文件上传的网址实现js代码
2013/03/25 Javascript
jQuery回车实现登录简单实现
2013/08/20 Javascript
jQuery实现图片信息的浮动显示实例代码
2013/08/28 Javascript
js 获取时间间隔实现代码
2014/05/12 Javascript
js图片轮播手动切换效果
2015/11/10 Javascript
JS修改地址栏参数实例代码
2016/06/14 Javascript
将鼠标焦点定位到文本框最后(代码分享)
2017/01/11 Javascript
Bootstrap缩略图与警告框学习使用
2017/02/08 Javascript
获取当前按钮或者html的ID名称实例(推荐)
2017/06/23 Javascript
vue2项目使用sass的示例代码
2017/06/28 Javascript
基于js中this和event 的区别(详解)
2017/10/24 Javascript
基于layPage插件实现两种分页方式浅析
2019/07/27 Javascript
JS原型prototype和__proto__用法实例分析
2020/03/14 Javascript
JS如何实现手机端输入验证码效果
2020/05/13 Javascript
Vue 禁用浏览器的前进后退操作
2020/09/04 Javascript
零基础写python爬虫之抓取百度贴吧并存储到本地txt文件改进版
2014/11/06 Python
轻松实现python搭建微信公众平台
2016/02/16 Python
Python smtplib实现发送邮件功能
2018/05/22 Python
python相对企业语言优势在哪
2020/06/12 Python
美国知名的百货清仓店:Neiman Marcus Last Call
2016/08/03 全球购物
Camille Jewelry官网:现代女性时尚首饰
2019/07/07 全球购物
Vector, ArrayList, HashTable, HashMap哪些是线程安全的,哪些不是
2015/10/12 面试题
小学先进集体事迹材料
2014/05/31 职场文书
路政管理求职信
2014/06/18 职场文书
小学教师师德师风个人整改措施
2014/09/18 职场文书
户籍证明模板
2014/09/28 职场文书
教师批评与自我批评发言稿
2014/10/15 职场文书
2015年民主评议党员工作总结
2015/05/19 职场文书
2016年元旦致辞
2015/08/01 职场文书
教你怎么用Python生成九宫格照片
2021/05/20 Python
Mysql中where与on的区别及何时使用详析
2021/08/04 MySQL
Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次
2022/04/24 Java/Android