[Node] 逃离回调地狱
逃离Node回调地狱
Background :
在Node中,函数的返回结果大多利用回调的方式处理。如简单的判断文件是否存在并读取内容:
var fs = require('fs');
fs.exists('path/to/file', function (exists) {
if (exists) {
fs.readFile('path/to/file', function (err, data) {
if (err) {
console.log('error: ', err);
} else {
console.log(data);
}
});
}
});
这里暂不考虑
existsSync和readFileSync这类函数,因为并不是所有函数都有对应的Sync函数,回调形式是Node的主角。
如上述示例,当回调嵌套过多时,代码的可读性将会严重下降。这就是所谓的回调地狱。
Solution :
关于回调地狱,网上有很多解决方案。一般是利用promise,async或者Generator来解决回调嵌套。
本文给大家介绍一种新的解决方案:await(个人认为比之前的看到的promise或者async的方案好很多)。
await是ES7的特性,尽管Node的最新版本(6.4.0)已经支持大多数ES2015(ES6)特性,但是await并不被Node支持。
TypeScript
TypeScript是具有类型系统的JavaScript超集。 它可以编译成普通的JavaScript代码。 TypeScript支持任意浏览器,任意环境,任意系统并且是开源的。
利用TypeScript中的async/await可以很好的解决回调地狱:
import * as fs from 'fs';
async function existsAsync(filePath: string): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
fs.exists(filePath, (exists: boolean) => {
resolve(exists);
});
});
}
async function readFileAsync(filePath: string, encoding: string = 'utf8'): Promise<string> {
return new Promise<string>((resolve, reject) => {
fs.readFile(filePath, encoding, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
async function main(): Promise<void> {
let exists: boolean = await existsAsync('path/to/file');
if (exists) {
let fileContent: string = await readFileAsync('path/to/file').catch((reason) => {
console.log('rejected: ', reason);
});
console.log(fileContent);
}
}
main().then(() => {
console.log('problem solved');
});
Explanation :
由于ES2015尚未包含await特性,所以TypeScript中的await在编译成js之后利用的是Generator来实现await效果的。
TypeScript编译的target默认是ES5,所以想使用async/await要把
tsconfig.json中的target属性改为es2015。
Conclusion :
利用TypeScript中的async/await可以将Node中的回调扁平化,比promise式的链式调用更易读。个人认为是解决回调地狱的首选方案。
TypeScript作为js的超集,可以用在任何使用js的场景。配合typings和VS code的IntelliSense,写js再也不痛苦啦~
[Node] 逃离回调地狱的更多相关文章
- 避免Node.js中回调地狱
为了解决这个阻塞问题,JavaScript严重依赖于回调,这是在长时间运行的进程(IO,定时器等)完成后运行的函数,因此允许代码执行经过长时间运行的任务. downloadFile('example. ...
- ES6(promise)_解决回调地狱初体验
一.前言 通过这个例子对promise解决回调地狱问题有一个初步理解. 二.主要内容 1.回调地狱:如下图所示,一个回调函数里面嵌套一个回调函数,这样的代码可读性较低也比较恶心 2.下面用一个简单的例 ...
- JavaScript 中回调地狱的今生前世
1. 讲个笑话 JavaScript 是一门编程语言 2. 异步编程 JavaScript 由于某种原因是被设计为单线程的,同时由于 JavaScript 在设计之初是用于浏览器的 GUI 编程,这也 ...
- JavaScript异步编程__“回调地狱”的一些解决方案
异步编程在JavaScript中非常重要.过多的异步编程也带了回调嵌套的问题,本文会提供一些解决“回调地狱”的方法. setTimeout(function () { console.log('延时触 ...
- [译] 回调地狱——JavaScript异步编程指南
原文:Callback Hell 什么是 “回调地狱”? 在 JavaScript 中,我们经常通过回调来实现异步逻辑,一旦嵌套层级多了,代码结构就容易变得很不直观,最后看起来像这样: fs.read ...
- Promise如何解决回调地狱
为什么要有promise:解决(回调地狱)的问题 ### 回调地狱: ```js //跟以前的if条件地狱很像 // if(){ // if(){ // if(){ // } // } //} $.g ...
- Node.js回调概念
什么是回调? 回调是一个异步等效的功能.在完成特定任务回调函数被调用. Node大量使用了回调.Node的所有的API都支持回调这样的一种方式. 例如,一个函数读取一个文件可能开始读取文件,并使得下一 ...
- iOS 如何优雅的处理“回调地狱Callback hell”(一) (下)
了解完流程之后,就可以开始继续研究源码了.在PromiseKit当中,最常用的当属then,thenInBackground,catch,finally - (PMKPromise *(^)(id)) ...
- iOS 如何优雅的处理“回调地狱Callback hell”(一) (上)
前言 最近看了一些Swift关于封装异步操作过程的文章,比如RxSwift,RAC等等,因为回调地狱我自己也写过,很有感触,于是就翻出了Promise来研究学习一下.现将自己的一些收获分享一下,有错误 ...
随机推荐
- whoosh使用笔记
1. whoosh安装 pip install Whoosh 2. 添加索引 第一步:生成schema 第二步:根据schema生成index.index就是一个目录中的一堆文件 (针对某个目录,调 ...
- HDU 1394 Minimum Inversion Number 线段树
题目: http://acm.hdu.edu.cn/showproblem.php?pid=1394 没看到多组输入,WA了一万次...... 其实很简单,有人暴力过得,我感觉归并排序.二叉排序树求逆 ...
- php的ftp类
1.需求 了解php的ftp使用 2.例子 使用CI封装好的ftp类库 上传 $this->load->library('ftp'); $config['hostname'] = 'ftp ...
- iOS开发者计划(转)
苹果对软件和开发者的管理十分严格,你只有加入了Apple Developer计划之后,才能将你的软件放到真机上运行或者发布到App Store上去.这种方法看似麻烦,但是却有效的解决了盗版和劣质软件充 ...
- memcached-win32-1.4.4-14 help doc
memcached-win32-1.4.4-14 cmd打开命令窗口,转到解压的目录,输入 “memcached.exe -d install”. 使用telnet命令 验证缓存服务器是否可用.tel ...
- 关于Action中ValidateXXX方法校验一次失败后\导致以后一直返回input视图的情况
问题: 使用struts2的validateXXX()进行验证,出错后自动返回之前的画面,但是Form中的数据全部丢失了,如何才能保存出错前的Form是要解决的问题. 调查: 调查后发 ...
- PS命令删除所有EXCHANGE2013内用户邮件
因为在测试的时间产生了大量测试邮件,所以在正式上线前,要删除所有用户的邮件. 命令如下: Get-Mailbox | Search-Mailbox -DeleteContent
- 李洪强iOS开发Swift篇—09_属性
李洪强iOS开发Swift篇—09_属性 一.类的定义 Swift与Objective-C定义类的区别 Objective-C:一般需要2个文件,1个.h声明文件和1个.m实现文件 Swift:只需要 ...
- Ubuntu下安装Qt4.5(包括X86和ARM版本)
条件:TQ2440开发板,虚拟机安装的Ubuntu10.04,安装好天嵌自带的GCC交叉编译器参考:http://blog.csdn.net/newnewman80/article/details/6 ...
- Perl脚本学习经验(三)--Perl中ftp的使用
使用use Net::FTP;Demo: my $Server = '192.168.1.1'; my $User = 'admin'; my $Password = 'admin' ...