async/await 是 ES2017 (ES8) 引入的处理异步操作的语法糖,它基于 Promise,但让异步代码看起来和同步代码一样,极大地提高了代码的可读性和可维护性。
async
关键字,表示该函数是异步的async function foo() {
return 'Hello';
}
// 等价于
function foo() {
return Promise.resolve('Hello');
}
await
只能在 async 函数内部使用async function bar() {
const result = await somePromise;
console.log(result);
}
function fetchData() {
return new Promise(resolve => {
setTimeout(() => resolve('Data loaded'), 1000);
});
}
async function getData() {
console.log('Fetching data...');
const data = await fetchData();
console.log('Data:', data);
return data;
}
getData().then(data => console.log('Final:', data));
async function fetchWithError() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error);
throw error; // 可以选择重新抛出错误
}
}
async function parallel() {
const [result1, result2] = await Promise.all([
fetch(url1),
fetch(url2)
]);
// 处理结果...
}
不要滥用 await:不必要的 await 会导致性能下降
// 不好 - 两个请求会顺序执行
async function sequential() {
const a = await fetchA();
const b = await fetchB();
return a + b;
}
// 好 - 两个请求并行执行
async function parallel() {
const [a, b] = await Promise.all([fetchA(), fetchB()]);
return a + b;
}
顶层 await:在 ES2022 中,可以在模块顶层使用 await
// 模块中
const data = await fetchData();
export default data;
循环中的 await:注意 forEach 和 map 中的 await 行为
// 这样不会按预期工作
items.forEach(async item => {
await processItem(item);
});
// 应该使用 for...of
for (const item of items) {
await processItem(item);
}
// 或者并行处理
await Promise.all(items.map(item => processItem(item)));
// Promise 方式
function getUserAndPosts(userId) {
return fetchUser(userId)
.then(user => fetchPosts(user.id))
.then(posts => {
return { user, posts };
})
.catch(error => {
console.error('Error:', error);
});
}
// async/await 方式
async function getUserAndPosts(userId) {
try {
const user = await fetchUser(userId);
const posts = await fetchPosts(user.id);
return { user, posts };
} catch (error) {
console.error('Error:', error);
}
}
async/await 让异步代码更易于编写和理解,是现代 JavaScript 开发中处理异步操作的首选方式。