详解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 parseInt字符转化为数字函数使用小结
Nov 05 Javascript
给超链接添加特效鼠标移动展示提示信息且随鼠标移动
Oct 17 Javascript
jQuery入门之层次选择器实例简析
Dec 11 Javascript
javascript 分号总结及详细介绍
Sep 24 Javascript
微信小程序 vidao实现视频播放和弹幕的功能
Nov 02 Javascript
JavaScript实现同一个页面打开多张图片
Dec 29 Javascript
纯JS实现简单的日历
Jun 26 Javascript
vue动画效果实现方法示例
Mar 18 Javascript
详解async/await 异步应用的常用场景
May 13 Javascript
Vue项目接入Paypal实现示例详解
Jun 04 Javascript
15个简单的JS编码标准让你的代码更整洁(小结)
Jul 16 Javascript
uniapp微信小程序实现一个页面多个倒计时
Nov 01 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数字字符串左侧补0、字符串填充和自动补齐的几种方法
2014/05/10 PHP
php使用fsockopen函数发送post,get请求获取网页内容的方法
2014/11/15 PHP
PHP时间和日期函数详解
2015/05/08 PHP
php调用云片网接口发送短信的实现方法
2017/10/25 PHP
关于php支持的协议与封装协议总结(推荐)
2017/11/17 PHP
PHP中in_array的隐式转换的解决方法
2018/03/06 PHP
在Laravel 中实现是否关注的示例
2019/10/22 PHP
YII2框架中behavior行为的理解与使用方法示例
2020/03/13 PHP
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
2011/02/24 Javascript
jQuery ajax 路由和过滤器使用说明
2011/08/02 Javascript
JS动态修改iframe内嵌网页地址的方法
2015/04/01 Javascript
jQuery弹层插件jquery.fancybox.js用法实例
2016/01/22 Javascript
react native仿微信PopupWindow效果的实例代码
2017/08/07 Javascript
weebox弹出窗口不居中显示的解决方法
2017/11/27 Javascript
vue微信分享到朋友圈 vue微信发送给好友
2018/11/28 Javascript
详解node和ES6的模块导出与导入
2020/02/19 Javascript
如何使用原生Js实现随机点名详解
2021/01/06 Javascript
Python程序设计入门(3)数组的使用
2014/06/16 Python
Python中__call__用法实例
2014/08/29 Python
Python基础语法(Python基础知识点)
2016/02/28 Python
python爬虫实战之最简单的网页爬虫教程
2017/08/13 Python
python使用Matplotlib绘制分段函数
2018/09/25 Python
Django查询优化及ajax编码格式原理解析
2020/03/25 Python
jupyternotebook 撤销删除的操作方式
2020/04/17 Python
大数据分析用java还是Python
2020/07/06 Python
用python实现前向分词最大匹配算法的示例代码
2020/08/06 Python
使用HTML5中的contentEditable来将多行文本自动增高
2016/03/01 HTML / CSS
从零实现一个自定义html5播放器的示例代码
2017/08/01 HTML / CSS
小溪流的歌教学反思
2014/02/13 职场文书
个人委托书范本
2014/04/02 职场文书
铣床操作工岗位职责
2014/06/13 职场文书
人大调研汇报材料
2014/08/14 职场文书
2014年客服工作总结范文
2014/11/13 职场文书
信仰观后感
2015/06/03 职场文书
山楂树之恋观后感
2015/06/11 职场文书
2019年英语版感谢信(8篇)
2019/09/29 职场文书