问题背景

在 js 异步编程中,通过回调函数实现。
当多个异步逻辑间产生顺序或关联逻辑,就会产生回调嵌套(回调地狱),导致代码丑陋且难以阅读,形如:

fetch(function() {
  fetch(function() {
    // ...
  });
});

看了阮一峰老师的文章小结为:早期解决方案是 Promise,将横向代码通过 then 包装为纵向,进一步引出 Generator,而 async/await 即是 Generator 的语法糖。

简单说,回调嵌套问题优化方案,根据时间线整理:
回调嵌套 -> Promise -> Generator(async/await)

使用 async/await 解决回调嵌套问题

看案例 index.html(可保存到本地运行):

<!DOCTYPE html>
<html>
<head>
    <title>Async/Await Example</title>
</head>
<body>
<script>
function callapi(v) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://h.lukachen.work/api.php?arg=' + v, true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    resolve(xhr.responseText);
                } else {
                    reject(xhr.statusText);
                }
            }
        };
        xhr.send();
    });
}
async function run() {
    try {
        var res1 = await callapi(1);
        console.log(res1);
        var resObject = JSON.parse(res1)
        var res2 = await callapi(resObject.data);
        console.log(res2);
    } catch (error) {
        console.log(error);
    }
}
run();
</script>
</body>
</html>

上述案例中,两次 callapi,第二次使用了第一次的返回值,await 方法阻塞当前行代码直到异步响应完成,使得异步代码可以用同步的写法,解决了回调嵌套问题。

附录

阮一峰老师针对 async、Generator、Promise 做了比较详细的解释,详情可查阅:
http://www.ruanyifeng.com/blog/2015/05/async.html
https://www.ruanyifeng.com/blog/2015/04/generator.html

文章目录