JS 的异步处理:Promise、Generator 与 async/await
Promise 对象
含义:
Promise 是一种异步编程解决方案,用于处理异步操作,并避免“回调地狱”问题。
优点:
- 链式编程:相比传统的回调函数和事件,Promise 更加合理和优雅,支持链式调用,解决了回调地狱的问题。
- 状态不可变:Promise 的结果有成功和失败两种状态,一旦状态确定,外界无法改变。
基本用法:
const p = new Promise(function(resolve, reject) {
if (success) {
resolve('成功的结果');
} else {
reject('失败的结果');
}
});
p.then(function(res) {
// 接收 resolve 传来的数据,处理成功逻辑
}, function(err) {
// 接收 reject 传来的数据,处理失败逻辑
});
p.catch(function(err) {
// 捕捉错误,或处理 then() 中的运行报错
});
p.finally(function() {
// 不论成功或失败都执行
});
常用 API
- resolve:返回异步操作成功的结果。
- reject:返回异步操作失败的结果。
- then:执行 Promise 成功状态时的操作。
- catch:执行 Promise 失败状态时的操作。
- finally:不论成功或失败都执行的操作。
Promise.all
const p = Promise.all([p1, p2, p3]);
p
的状态由p1
、p2
、p3
决定:- 只有
p1
、p2
、p3
都成功,p
的状态才会是成功,返回值为p1
、p2
、p3
的结果数组。 - 只要其中一个失败,
p
就会是失败状态,返回第一个失败的结果。
- 只有
Generator 函数
含义:
Generator 函数是 ES6 提供的另一种异步编程解决方案,与传统函数语法完全不同。
基本用法:
function* helloGenerator() {
yield 'hello';
yield 'Generator';
return 'over';
}
let hw = helloGenerator();
hw.next(); // {value: "hello", done: false}
hw.next(); // {value: "Generator", done: false}
hw.next(); // {value: "over", done: true}
hw.next(); // {value: undefined, done: true}
特征:
function
关键字与函数名之间有一个星号*
。- 函数内部使用
yield
表达式定义不同的状态。 - 通过
next
方法逐步执行函数,获取每个yield
的返回值。
async 函数
含义:
async 函数是 ES2017 标准引入的异步编程语法糖,使得异步操作更加方便,内部基于 Promise
实现。
基本用法:
function get1() {
return new Promise((resolve, reject) => {
setTimeout(() => { resolve(1); }, 2000);
});
}
async function getSet() {
const n = await get1();
return n;
}
getSet().then(console.log); // 输出 1
说明:
await
只能在async
函数内使用,用于等待一个 Promise 对象的结果。- 如果
await
后面的不是 Promise 对象,直接返回该值。
优点:
- 内置执行器:async 函数自动执行,无需显式调用
next()
。 - 语义更清晰:
async
表示函数内部有异步操作,await
表示需要等待结果。 - 返回值是 Promise:async 函数返回 Promise 对象,可以使用
then
方法处理。 - 更广的适用性:
await
后可以是 Promise 对象,也可以是普通值。
额外说明:
- 多个
await
命令可以并行执行,使用Promise.all
或分别调用,提升性能。
async function getSet() {
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
return [foo, bar];
}
或
async function getSet() {
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
return [foo, bar];
}
通过以上异步处理方法,JavaScript 的异步编程变得更加灵活和直观,能够有效提升代码的可读性和维护性。