JavaScript 是单线程语言,异步编程是其核心特性之一。本文从回调到 async/await 逐步梳理。

回调函数

最早的异步处理方式,但容易造成”回调地狱”。

1
2
3
4
5
fs.readFile('a.txt', function(err, data) {
fs.readFile('b.txt', function(err, data2) {
// 嵌套越来越深...
});
});

Promise

ES6 引入,解决回调地狱问题。

1
2
3
4
fetch('/api/data')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));

Promise 静态方法

1
2
3
Promise.all([p1, p2, p3])     // 全部成功才成功
Promise.race([p1, p2, p3]) // 第一个完成即返回
Promise.allSettled([p1, p2]) // 等待全部完成(无论成败)

async/await

ES2017 引入,异步代码同步写。

1
2
3
4
5
6
7
8
9
async function loadData() {
try {
const res = await fetch('/api/data');
const data = await res.json();
return data;
} catch (err) {
console.error(err);
}
}

总结

方式 出现时间 适用场景
回调 ES5 简单异步操作
Promise ES6 链式调用、并发控制
async/await ES2017 复杂异步流程