逃离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);
}
});
}
});

这里暂不考虑existsSyncreadFileSync这类函数,因为并不是所有函数都有对应的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] 逃离回调地狱的更多相关文章

  1. 避免Node.js中回调地狱

    为了解决这个阻塞问题,JavaScript严重依赖于回调,这是在长时间运行的进程(IO,定时器等)完成后运行的函数,因此允许代码执行经过长时间运行的任务. downloadFile('example. ...

  2. ES6(promise)_解决回调地狱初体验

    一.前言 通过这个例子对promise解决回调地狱问题有一个初步理解. 二.主要内容 1.回调地狱:如下图所示,一个回调函数里面嵌套一个回调函数,这样的代码可读性较低也比较恶心 2.下面用一个简单的例 ...

  3. JavaScript 中回调地狱的今生前世

    1. 讲个笑话 JavaScript 是一门编程语言 2. 异步编程 JavaScript 由于某种原因是被设计为单线程的,同时由于 JavaScript 在设计之初是用于浏览器的 GUI 编程,这也 ...

  4. JavaScript异步编程__“回调地狱”的一些解决方案

    异步编程在JavaScript中非常重要.过多的异步编程也带了回调嵌套的问题,本文会提供一些解决“回调地狱”的方法. setTimeout(function () { console.log('延时触 ...

  5. [译] 回调地狱——JavaScript异步编程指南

    原文:Callback Hell 什么是 “回调地狱”? 在 JavaScript 中,我们经常通过回调来实现异步逻辑,一旦嵌套层级多了,代码结构就容易变得很不直观,最后看起来像这样: fs.read ...

  6. Promise如何解决回调地狱

    为什么要有promise:解决(回调地狱)的问题 ### 回调地狱: ```js //跟以前的if条件地狱很像 // if(){ // if(){ // if(){ // } // } //} $.g ...

  7. Node.js回调概念

    什么是回调? 回调是一个异步等效的功能.在完成特定任务回调函数被调用. Node大量使用了回调.Node的所有的API都支持回调这样的一种方式. 例如,一个函数读取一个文件可能开始读取文件,并使得下一 ...

  8. iOS 如何优雅的处理“回调地狱Callback hell”(一) (下)

    了解完流程之后,就可以开始继续研究源码了.在PromiseKit当中,最常用的当属then,thenInBackground,catch,finally - (PMKPromise *(^)(id)) ...

  9. iOS 如何优雅的处理“回调地狱Callback hell”(一) (上)

    前言 最近看了一些Swift关于封装异步操作过程的文章,比如RxSwift,RAC等等,因为回调地狱我自己也写过,很有感触,于是就翻出了Promise来研究学习一下.现将自己的一些收获分享一下,有错误 ...

随机推荐

  1. bzoj4038: 医疗援助

    Description 一只带着先进设备和药物的医疗团队来到了埃博拉病毒疫区的某个非洲国家.这个国家有n个村庄,均坐落在该国唯一的一条公路旁,n个村庄依次标号为1,2,…n.第i个村庄有a_i个埃博拉 ...

  2. 关于回波损耗 和 驻波比的摘要 Return Loss and VSWR

    关于回波损耗 和 驻波比的摘要 以下摘自:http://www.soontai.com/cal_rtvswr.html RL = 20log((VSWR+1) / (VSWR-1)) VSWR = ( ...

  3. jquery - 通过点击切换文字内容

    今天要写一个简单的显示/隐藏效果,本以为是挺简单的事儿,没想到还真因为基本功不扎实遇到了问题,这里跟大家分享一下. 百度了很多方法,精简能用的干货实在太少,最后还是通过去查jq的官方api才找到了解决 ...

  4. the apply of backbone

    http://www.developer.com/print/lang/jscript/creating-a-javascript-driven-online-notebook-with-backbo ...

  5. VMware配置回环地址用于测试

           我们在开发过程中,很可能需要一台服务器用于测试,在这种环境下,我们很可能需要用到vmware来构建这样的开发环境.但如果当前处在一个离线,或是不在网内的环境下,我们所搭建的环境有可能无法 ...

  6. ANDROID_MARS学习笔记_S05_006_距离传感器

    import android.app.Activity; import android.content.Context; import android.hardware.Sensor; import ...

  7. Perl脚本学习经验(四)--Perl中sftp的使用

    使用sftp,需要使用Except模块,该模块需要下载安装在perl目录下,可以上http://www.cpan.org/上下载对应的安装包:1. 用root用户登录环境:2. cd /usr/lib ...

  8. Hibernate:1对1关系总结。

    QQ和QQ空间是1对1关系:配置如下 一.主键关联,双方共同维护表关系,以主键关联 public class QQ { private Long id; private QQZone zone; } ...

  9. 【HDOJ】3061 Battle

    Dinic解网络流模板题目.队列用STL就TLE... /* 3061 */ #include <iostream> #include <string> #include &l ...

  10. 全球AI界最值得关注的十位科学家

    全球AI界最值得关注的十位科学家   我们可以看到AI已经从象牙塔里的高冷研究,逐步转换为科技公司.互联网公司的最核心竞争力.AI代表了这时代人类的前沿智慧,也正达到一种科学的极致. 这两天在美国加利 ...