详解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 相关文章推荐
从父页面读取和操作iframe中内容方法
Jul 25 Javascript
你必须知道的Javascript知识点之"单线程事件驱动"的使用
Apr 23 Javascript
写出高效jquery代码的19条指南
Mar 19 Javascript
JS、DOM和JQuery之间的关系示例分析
Apr 09 Javascript
js 动态为textbox添加下拉框数据源的方法
Apr 24 Javascript
浅析JavaScriptSerializer类的序列化与反序列化
Nov 22 Javascript
Angular将填入表单的数据渲染到表格的方法
Sep 22 Javascript
vue forEach循环数组拿到自己想要的数据方法
Sep 21 Javascript
JavaScript中十种一步拷贝数组的方法实例详解
Apr 22 Javascript
微信小程序API—获取定位的详解
Apr 30 Javascript
Layui Table js 模拟选中checkbox的例子
Sep 03 Javascript
.netcore+vue 实现压缩文件下载功能
Sep 24 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企业级应用之常见缓存技术篇
2011/01/27 PHP
php实例分享之mysql数据备份
2014/05/19 PHP
Yii2使用swiftmailer发送邮件的方法
2016/05/03 PHP
Yii2框架制作RESTful风格的API快速入门教程
2016/11/08 PHP
PHP数据库操作四:mongodb用法分析
2017/08/16 PHP
Laravel构建即时应用的一种实现方法详解
2017/08/31 PHP
PHP实现PDO操作mysql存储过程示例
2019/02/13 PHP
php字符串截取函数mb_substr用法实例分析
2019/06/25 PHP
JavaScript版TAB选项卡效果实例
2013/08/16 Javascript
jquery form 加载数据示例
2014/04/21 Javascript
jquery实现多条件筛选特效代码分享
2015/08/28 Javascript
jQuery实现百叶窗焦点图动画效果代码分享(附源码下载)
2016/03/14 Javascript
node.js实现端口转发
2016/04/14 Javascript
Json解析的方法小结
2016/06/22 Javascript
ES6中Array.find()和findIndex()函数的用法详解
2017/09/16 Javascript
Node.js readline 逐行读取、写入文件内容的示例
2018/03/01 Javascript
JavaScript的数据类型转换原则(干货)
2018/03/15 Javascript
layui使用数据表格实现购物车功能
2019/07/26 Javascript
layui实现数据分页功能
2019/07/27 Javascript
Vue.js桌面端自定义滚动条组件之美化滚动条VScroll
2020/12/01 Vue.js
有趣的python小程序分享
2017/12/05 Python
Windows下Anaconda2安装NLTK教程
2018/09/19 Python
Python之两种模式的生产者消费者模型详解
2018/10/26 Python
Django微信小程序后台开发教程的实现
2020/06/03 Python
15个Pythonic的代码示例(值得收藏)
2020/10/29 Python
瑞典轮胎在线:Tirendo.se
2018/06/21 全球购物
乌克兰在线电子产品商店:MTA
2019/11/14 全球购物
德国二手设计师时装和复古时装跳蚤市场:Mädchenflohmarkt
2020/11/09 全球购物
J2EE面试题集锦(附答案)
2013/08/16 面试题
校园安全检查制度
2014/02/03 职场文书
年终总结会主持词
2014/03/25 职场文书
住宅质量保证书
2014/04/29 职场文书
春风化雨观后感
2015/06/11 职场文书
2019自荐信该如何写呢?
2019/07/05 职场文书
利用JavaScript写一个简单计算器
2021/11/27 Javascript
Linux在两个服务器直接传文件的操作方法
2022/08/05 Servers