在Node中,函數的返回結果大多利用回調的方式處理。如簡單的判斷文件是否存在並讀取內容:javascript
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的主角。html
如上述示例,當回調嵌套過多時,代碼的可讀性將會嚴重降低。這就是所謂的回調地獄
。java
關於回調地獄,網上有不少解決方案。通常是利用promise,async或者Generator來解決回調嵌套。node
本文給你們介紹一種新的解決方案:await(我的認爲比以前的看到的promise或者async的方案好不少)。
await
是ES7的特性,儘管Node的最新版本(6.4.0)已經支持大多數ES2015(ES6)特性,可是await並不被Node支持。typescript
TypeScript是具備類型系統的JavaScript超集。 它能夠編譯成普通的JavaScript代碼。 TypeScript支持任意瀏覽器,任意環境,任意系統而且是開源的。
利用TypeScript中的async/await
能夠很好的解決回調地獄:json
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'); });
因爲ES2015還沒有包含await特性,因此TypeScript中的await在編譯成js以後利用的是Generator來實現await效果的。promise
TypeScript編譯的target默認是ES5,因此想使用async/await要把
tsconfig.json
中的target
屬性改成es2015
。瀏覽器
利用TypeScript中的async/await
能夠將Node中的回調扁平化,比promise式的鏈式調用更易讀。我的認爲是解決回調地獄的首選方案。async
TypeScript做爲js的超集,能夠用在任何使用js的場景。配合typings和VS code的IntelliSense,寫js不再痛苦啦~函數