详解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返回0-1之间随机数的方法
Apr 06 Javascript
JavaScript采用递归算法计算阶乘实例
Aug 04 Javascript
JS实现的四级密码强度检测功能示例
May 11 Javascript
详解react-router如何实现按需加载
Jun 15 Javascript
详解Vue-cli代理解决跨域问题
Sep 27 Javascript
jQuery 禁止表单用户名、密码自动填充功能
Oct 30 jQuery
JavaScript中的一些隐式转换和总结(推荐)
Dec 22 Javascript
基于node搭建服务器,写接口,调接口,跨域的实例
May 13 Javascript
vue数组对象排序的实现代码
Jun 20 Javascript
clipboard在vue中的使用的方法示例
Oct 19 Javascript
使用 Github Actions 自动部署 Angular 应用到 Github Pages的方法
Jul 20 Javascript
前端canvas中物体边框和控制点的实现示例
Aug 05 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
十天学会php(1)
2006/10/09 PHP
PHP数据库开发知多少
2006/10/09 PHP
PHP字符串的递增和递减示例介绍
2014/02/11 PHP
php实现的递归提成方案实例
2015/11/14 PHP
PHP中$GLOBALS['HTTP_RAW_POST_DATA']和$_POST的区别分析
2017/07/03 PHP
PHP数组访问常用方法解析
2020/09/05 PHP
关于实现代码语法标亮 dp.SyntaxHighlighter
2007/02/02 Javascript
javascript Array.remove() 数组删除
2009/08/06 Javascript
jQuery学习基础知识小结
2010/11/25 Javascript
Js四则运算函数代码
2012/07/21 Javascript
javascript搜索框点击文字消失失焦时文本出现
2014/09/18 Javascript
jQuery+css实现的时钟效果(兼容各浏览器)
2016/01/27 Javascript
javascript 小数乘法结果错误的处理方法
2016/07/28 Javascript
jQuery实现别踩白块儿网页版小游戏
2017/01/18 Javascript
vue.js+Element实现表格里的增删改查
2017/01/18 Javascript
d3.js中冷门却实用的内置函数总结
2017/02/04 Javascript
Angular2搜索和重置按钮过场动画
2017/05/24 Javascript
微信小程序onLaunch异步,首页onLoad先执行?
2018/09/20 Javascript
详解微信小程序用定时器实现倒计时效果
2019/04/30 Javascript
jQuery动态生成的元素绑定事件操作实例分析
2019/05/04 jQuery
微信公众号服务器验证Token步骤图解
2019/12/30 Javascript
基于Element的组件改造的树形选择器(树形下拉框)
2020/02/27 Javascript
jquery实现拖拽添加元素功能
2020/12/01 jQuery
[43:24]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS Liquid
2018/03/30 DOTA
python正则表达式面试题解答
2020/04/28 Python
使用python实现男神女神颜值打分系统(推荐)
2019/10/31 Python
使用python-Jenkins批量创建及修改jobs操作
2020/05/12 Python
美国皮靴公司自1863年:The Frye Company
2016/11/30 全球购物
师范毕业生自荐信
2013/10/17 职场文书
教师自荐信
2013/12/10 职场文书
服务员自我评价
2014/01/25 职场文书
体育教师个人的自我评价
2014/02/16 职场文书
课前三分钟演讲稿
2014/04/24 职场文书
赞美老师的演讲稿
2014/05/22 职场文书
党员个人总结范文
2015/02/14 职场文书
Win11 vmware不兼容怎么办?Win11与VMware虚拟机不兼容的解决方法
2023/01/09 数码科技