异步编程:Async/Await¶
概述¶
在 JavaScript 中,异步编程是处理耗时操作(如网络请求、文件读写等)的关键。ES8(ECMAScript 2017)引入了 async/await
语法,使得异步代码的编写和阅读更加直观和简洁。async/await
是基于 Promise 的语法糖,它允许我们以同步的方式编写异步代码。
基本概念¶
async
函数¶
async
函数是使用 async
关键字声明的函数。它总是返回一个 Promise 对象。如果函数返回值不是 Promise,它会被自动包装成一个 resolved 状态的 Promise。
async function myFunction() {
return "Hello, World!";
}
myFunction().then(alert); // 弹出 "Hello, World!"
await
表达式¶
await
关键字只能在 async
函数内部使用。它会暂停 async
函数的执行,等待 Promise 完成并返回其结果。如果 Promise 被拒绝,await
会抛出异常。
async function fetchData() {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
return data;
}
代码示例¶
示例 1: 基本用法¶
// 定义一个返回 Promise 的函数
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data fetched!");
}, 1000);
});
}
// 使用 async/await 处理异步操作
async function getData() {
console.log("Fetching data...");
let result = await fetchData(); // 等待 Promise 完成
console.log(result); // 输出 "Data fetched!"
}
getData();
解释: - fetchData
函数模拟了一个异步操作,1秒后返回数据。 - getData
函数使用 await
等待 fetchData
的结果,然后输出。
示例 2: 错误处理¶
// 定义一个可能失败的 Promise
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject("Error: Data could not be fetched!");
}, 1000);
});
}
// 使用 try/catch 处理错误
async function getData() {
try {
console.log("Fetching data...");
let result = await fetchData(); // 等待 Promise 完成
console.log(result);
} catch (error) {
console.error(error); // 输出 "Error: Data could not be fetched!"
}
}
getData();
解释: - fetchData
函数模拟了一个失败的异步操作。 - getData
函数使用 try/catch
捕获 await
抛出的异常。
示例 3: 并行执行多个异步操作¶
// 定义两个返回 Promise 的函数
function fetchUser() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ name: "John Doe" });
}, 1000);
});
}
function fetchPosts() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(["Post 1", "Post 2"]);
}, 1500);
});
}
// 并行执行多个异步操作
async function getUserAndPosts() {
let [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);
console.log(user); // 输出 { name: "John Doe" }
console.log(posts); // 输出 ["Post 1", "Post 2"]
}
getUserAndPosts();
解释: - fetchUser
和 fetchPosts
函数分别模拟了两个异步操作。 - getUserAndPosts
函数使用 Promise.all
并行执行这两个操作,并使用 await
等待它们全部完成。
练习题¶
练习 1: 基本 async/await
使用¶
编写一个 async
函数 fetchUserData
,它调用一个返回 Promise 的函数 fetchUser
,并使用 await
等待结果。fetchUser
函数应该在 1 秒后返回用户数据 { name: "Alice", age: 25 }
。
练习 2: 错误处理¶
修改上面的 fetchUserData
函数,使其在 fetchUser
失败时捕获错误并输出 "Failed to fetch user data"。
练习 3: 并行执行¶
编写一个 async
函数 fetchAllData
,它并行调用 fetchUser
和 fetchPosts
函数,并输出用户数据和帖子列表。fetchPosts
函数应该在 1.5 秒后返回帖子列表 ["Post 1", "Post 2"]
。
总结¶
async/await
是 ES8 引入的语法糖,用于简化异步代码的编写。async
函数总是返回一个 Promise。await
关键字只能在async
函数内部使用,它会暂停函数的执行,直到 Promise 完成。- 使用
try/catch
可以捕获await
抛出的异常。 - 使用
Promise.all
可以并行执行多个异步操作。
通过掌握 async/await
,你可以编写出更加简洁、易读的异步代码,提高开发效率和代码质量。