ES6 系列之异步处理实战
前言
我们以查找指定目录下的最大文件为例,感受从
回调函数 -> 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);
});
ES6 系列
ES6 系列目录地址:https://github.com/mqyqingfeng/Blog
ES6 系列预计写二十篇左右,旨在加深 ES6 部分知识点的理解,重点讲解块级作用域、标签模板、箭头函数、Symbol、Set、Map 以及 Promise 的模拟实现、模块加载方案、异步处理等内容。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
来源:https://segmentfault.com/a/1190000016792362
ES6 系列之异步处理实战的更多相关文章
- ES6系列文章 异步神器async-await
关于异步处理,ES5的回调使我们陷入地狱,ES6的Promise使我们脱离魔障,终于.ES7的async-await带我们走向光明.今天就来学习一下 async-await. async-await和 ...
- ES6 Generators的异步应用
ES6 Generators系列: ES6 Generators基本概念 深入研究ES6 Generators ES6 Generators的异步应用 ES6 Generators并发 通过前面两篇文 ...
- ES6 系列之 Babel 是如何编译 Class 的(下)
前言 ES5 寄生组合式继承 function Parent (name) { this.name = name; } Parent.prototype.getName = function () { ...
- ES6系列之项目中常用的新特性
ES6系列之项目中常用的新特性 ES6常用特性 平时项目开发中灵活运用ES6+语法可以让开发者减少很多开发时间,提高工作效率.ES6版本提供了很多新的特性,接下来我列举项目中常用的ES6+的特性: l ...
- QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL
QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL 课程1 C语言程序设计高级实用速成课程 基础+进阶+自学 课程2 C语言程序设计Windows GDI图形绘 ...
- 前端构建大法 Gulp 系列 (四):gulp实战
前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp专家 前 ...
- [js高手之路] es6系列教程 - 对象功能扩展详解
第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...
- [js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解
接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续. 在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢? 可迭代的对象一般 ...
- 大白话,讲编程之《ES6系列连载》汇总
如果你经历过2,3年前的前端开发,你一定感受过兼容IE6,7的痛苦,一定用过网页三剑客的dreamweaver编写html,面试的时候面试官一定会问你:会用PS切图吗? 刚开始的时候你发现,web前端 ...
随机推荐
- html b标签 语法
html b标签 语法 标签b是什么意思? b的意思是bold,b标签主要用于html中规定粗体文本,该标签内的字符将被设为粗体.B标签所传达的意思只是加粗,没有任何其它的作用. 作用:规定粗体文本. ...
- [Usaco2007 Jan]Balanced Lineup排队
[Usaco2007 Jan]Balanced Lineup排队 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 2333 Solved: 1424 Des ...
- max pool实现
题目 二维矩阵(nm) 求每个(lw)的子矩阵的最大元素, 就是一维滑动窗口的升级版 自己瞎掰的题解 #include <bits/stdc++.h> using namespace st ...
- (44)FreeRTOS学习之一
一:FreeRTOS 作为一个轻量级的操作系统,FreeRTOS 提供的功能包括:任务管理.时间管理.信号量.消息队列.内存管理.记录功能等,可基本满足较小系统的需要.FreeRTOS 内核支持优先级 ...
- springboot切换配置
1.默认只有一个application.properties文件 1)删除properties文件,换成yml方式.新增dev,prod两个文件 2)配置application.yml文件:actio ...
- Spotlight_on_linux 安装和监控
一.下载 下载并安装 Spotlight_on_linux 二.建立连接 注意:用户名不能使用root连接,需要自己创建个用户root权限的用户 1.useradd xiaoxitest 2.p ...
- kubernetes master 更换ip(单节点)
问题分析 master ip地址变更以后,我们首先应该检查以下内容: /etc/kubernetes/manifests下面的config配置文件,替换里面对应的ip 相关的证书文件 客户端文件 解决 ...
- maven 成长之路
1配置maven 环境变量 新建系统变量 M2_HOME :E:\apache-maven-3.5.2 在系统变量 path中添加 E:\apache-maven-3.5.2\bin 运行 mvn - ...
- 三、Appium-python-UI自动化之元素定位uiautomatorviewer
uiautomatorviewer是android-sdk自带的一个元素定位工具,非常简单好用,使用uiautomatorviewer,可以检查一个应用的UI来查看应用的布局和组件以及相关的属性. 一 ...
- 方法二破解:Excel工作表保护密码
最简单,复制整表,粘贴在全新的表中.但是有时候会丢失一些元素 在excel2016中实测验证过有效 第1步:在工作表菜单栏上添加[开发工具].方法是:依次单击[文件]--->[选项]---> ...