[Node] 逃離回調地獄

逃離Node回調地獄

Background :

在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);
            }
        });
    }
});

這裏暫不考慮existsSyncreadFileSync這類函數,由於並非全部函數都有對應的Sync函數,回調形式是Node的主角。html

如上述示例,當回調嵌套過多時,代碼的可讀性將會嚴重降低。這就是所謂的回調地獄java

Solution :

關於回調地獄,網上有不少解決方案。通常是利用promise,async或者Generator來解決回調嵌套。node

本文給你們介紹一種新的解決方案:await(我的認爲比以前的看到的promise或者async的方案好不少)。
await是ES7的特性,儘管Node的最新版本(6.4.0)已經支持大多數ES2015(ES6)特性,可是await並不被Node支持。typescript

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');
});

Explanation :

因爲ES2015還沒有包含await特性,因此TypeScript中的await在編譯成js以後利用的是Generator來實現await效果的。promise

TypeScript編譯的target默認是ES5,因此想使用async/await要把tsconfig.json中的target屬性改成es2015瀏覽器

Conclusion :

利用TypeScript中的async/await能夠將Node中的回調扁平化,比promise式的鏈式調用更易讀。我的認爲是解決回調地獄的首選方案。async

TypeScript做爲js的超集,能夠用在任何使用js的場景。配合typings和VS code的IntelliSense,寫js不再痛苦啦~函數

相關文章
相關標籤/搜索