在处理javascript中异步的时候,回调往往是最让人恶心的,之前介绍过用Promise来处理异步的问题,但是即使用上了Promise,在处理回调上还是会有各种嵌套,今天来介绍下ES7中的async/await,由于在Nodejs中还未得到支持,所以需要借助一些npm包来实践,在这里用的是asyncawait

先来个原生文件读取的例子:

const fs = require("fs");
fs.readFile("test.txt", (ex, res) => {
   console.log(res.toString()); 

   //   do something...

   fs.readFile("test2.txt", (ex, res) => {
        console.log(res.toString());

        //  do something
   });
});

//  控制台输出
xxxxx
yyyyy

下面我们再用async/await实现一遍:

const async = require("asyncawait").async;
const await = require("asyncawait").await;
let readFile = function(path) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, (ex, res) => {
            if (ex) {
                reject(ex);
            }
            resolve(res);
        });
    });
}

let asyncReadFile = async(() => {

    let fs = await (readFile("test.txt"));
    let fs2 = await (readFile("test2.txt"));

    console.log(fs.toString());
    console.log(fs2.toString());
});

asyncReadFile();

虽然代码可能比上面的多了一点,但是已经完全看不到回调嵌套的影子了,也能完成同样的功能,何乐而不为。😉

下面我们再来模拟一个异步请求的例子:

const async = require("asyncawait").async;
const await = require("asyncawait").await;
const http = require("http");

http.createServer((req, res) => {

    switch (req.url) {

        case "/async-await":
            setTimeout(() => {
                res.writeHead(200, { "Content-Type": "text/plain" });
                res.end("request end");
            }, 5000);
            break;

        case "/async-await2":
            setTimeout(() => {
                res.writeHead(200, { "Content-Type": "text/plain" });
                res.end("request end2");
            }, 8000);
            break;

        default:
            break;

    }
}).listen(3000, "127.0.0.1");

let requestUrl = function(path) {
    return new Promise((resolve, reject) => {
        http.get({
            hostname: 'localhost',
            port: 3000,
            path: path,
            agent: false
        }, (res) => {
            res.on("data", (data) => {
                resolve(data);
            });
            res.on("error", (ex) => {
                reject(ex);
            })
        });
    });
}

let asyncRequest = async(() => {
    let resp, resp2;
    await (requestUrl("/async-await").then((res) => {
        console.log(res.toString());
        resp = res.toString();
    }).catch((ex) => {
        resp = "发生错误!";
    }));

    await (requestUrl("/async-await2").then((res) => {
        resp2 = res.toString();
    }).catch((ex) => {
        resp = "发生错误!";
    }));
    console.log(resp);
    console.log(resp2);
});

asyncRequest();

//  控制台输出
request end
request end2

由此我们可以将async/await用在很多地方,比如例子中的文件读取、异步请求、nodejs中的查询数据库等等。