JavaScript 是单线程执行的,但通过异步编程可以处理耗时操作而不阻塞主线程。本文详细介绍 JavaScript 的异步编程机制。

什么是异步编程?

异步编程是一种编程范式,允许程序在等待某些操作完成时继续执行其他代码。

回调函数

最简单的异步方式:

1
2
3
4
5
6
7
8
9
console.log('开始');

setTimeout(function() {
console.log('两秒后执行');
}, 2000);

console.log('结束');

// 输出顺序:开始 -> 结束 -> 两秒后执行

Promise

Promise 是 ES6 引入的异步解决方案:

1
2
3
4
5
6
7
8
9
10
11
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
resolve('成功');
// 或 reject('失败');
}, 1000);
});

promise
.then(result => console.log(result))
.catch(error => console.error(error));

async/await

ES2017 引入的语法糖,让异步代码看起来像同步代码:

1
2
3
4
5
6
7
8
async function fetchData() {
try {
const result = await promise;
console.log(result);
} catch (error) {
console.error(error);
}
}

总结

  • 回调函数:最基础的方式,容易产生回调地狱
  • Promise:链式调用,避免回调地狱
  • async/await:最优雅的写法,推荐使用

深入理解

Promise 的三种状态

1
2
3
4
5
6
7
8
// pending(进行中)
// fulfilled(已成功)
// rejected(已失败)

let p = new Promise((resolve, reject) => {
// resolve('成功') // 状态变为 fulfilled
// reject('失败') // 状态变为 rejected
});

并发请求

1
2
3
4
5
6
7
// Promise.all - 全部成功才成功
Promise.all([p1, p2, p3])
.then(results => console.log(results));

// Promise.race - 谁快用谁
Promise.race([p1, p2, p3])
.then(result => console.log(result));