[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来研究学习一下.现将自己的一些收获分享一下,有错误 ...
随机推荐
- nRF52系列——nRF52832来袭
nRF52系列——nRF52832来袭 Nordic凭借着在无线技术的数十年深耕,推出第一个μBlue芯片-- nRF8001.其低功耗等特性在当时吸引了无数厂商的目光,并将这产品应用到多个领域,再之 ...
- c# 如何通过反射 获取\设置属性值、
//定义类public class MyClass{public int Property1 { get; set; }}static void Main(){MyClass tmp_Class = ...
- Xcode 证书生成、设置、应用
Xcode 证书生成.设置.应用,与大家分享.如果按下面步骤还不能编译成功,我手把手教你. 开发环境: Mac OS lion 10.7.4 XCode 4.3.3 1 点击钥匙图标 ...
- Apache httpd.conf的翻译
本人初学,15年暑假翻译了一些,前几天翻译完,有机器翻译,也有自己翻译的内容,不准确之处请指出. --------------------------------------------------- ...
- IE8下String的Trim()方法失效的解决方法
String的Trim()方法失效,在ie8下是有这样的情况的,解决方法也很简单使用$.trim(str)即可,需要的朋友可以了解下 用jquery的trim()方法,$.trim(str)就可以了.
- The Bellman-Ford algorithm
This algorithm deals with the general case, where G is a directed, weight graph, and it can contains ...
- SQL2005 安装时 “性能监视器计数器要求(错误)” 解决方案
转自SQL2005 安装时 "性能监视器计数器要求(错误)" 解决方案 出现此类问题一般都是在非法卸载sql2005出现的 在 "开始" --> &qu ...
- SPRING IN ACTION 第4版笔记-第二章-004-Bean是否单例
spring的bean默认是单例,加载容器是会被化,spring会拦截其他再次请求bean的操作,返回spring已经创建好的bean. It appears that the CompactDisc ...
- 控件构造函数需要的AOwner是TComponent,而不是Parent
普通控件都只有一个构造函数,但是这个构造函数却强迫指定AOwner,也就是说,VCL希望将所有控件(至少是所有可视化控件)全部置于它的管理之下.至于到底显示不显示,那是另一个层次的问题.这个问题其实挺 ...
- in an effort to
What does "in an effort" to mean? I personally consider in an effort to a stock phrase1. T ...