async关键字声明的异步函数。
// 声明async函数
async function fetchData() {
return "东巴文";
}
// 函数表达式
const getData = async function() {
return "db-w.cn";
};
// 箭头函数
const fetchUser = async () => {
return { name: "东巴文" };
};
// 类方法
class Api {
async load() {
return "数据";
}
}
// async函数总是返回Promise
async function greet() {
return "Hello";
}
console.log(greet()); // Promise { "Hello" }
greet().then(value => {
console.log(value); // "Hello"
});
// 返回Promise
async function fetchUser() {
return fetch("/api/user").then(r => r.json());
}
// 返回值会被Promise.resolve包装
async function getValue() {
return Promise.resolve("已解决的Promise");
}
getValue().then(v => console.log(v)); // "已解决的Promise"
等待Promise解决。
// await等待Promise解决
async function fetchData() {
const response = await fetch("/api/data");
const data = await response.json();
return data;
}
// await只能在async函数内使用
async function example() {
const value = await Promise.resolve("东巴文");
console.log(value); // "东巴文"
}
// 错误:不能在普通函数中使用
function wrong() {
// await Promise.resolve("错误"); // SyntaxError
}
async function demo() {
console.log("1. 开始");
const value = await Promise.resolve("东巴文");
console.log("2. 获取值:", value);
console.log("3. 结束");
}
console.log("a. 调用前");
demo();
console.log("b. 调用后");
// 输出顺序:
// a. 调用前
// 1. 开始
// b. 调用后
// 2. 获取值: 东巴文
// 3. 结束
async function example() {
// 非Promise值会被立即解决
const value1 = await "字符串";
console.log(value1); // "字符串"
const value2 = await 123;
console.log(value2); // 123
const value3 = await { name: "东巴文" };
console.log(value3); // { name: "东巴文" }
// 等价于
const value4 = await Promise.resolve("值");
}
使用try-catch处理异步错误。
async function fetchData() {
try {
const response = await fetch("/api/data");
if (!response.ok) {
throw new Error(`HTTP错误: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("请求失败:", error);
throw error; // 可以重新抛出
}
}
// 使用
fetchData()
.then(data => console.log(data))
.catch(error => console.error("外层捕获:", error));
async function process() {
try {
const user = await getUser();
const posts = await getPosts(user.id);
const comments = await getComments(posts[0].id);
return comments;
} catch (error) {
console.error("处理失败:", error);
return null;
}
}
// 分开处理
async function processSeparate() {
try {
const user = await getUser();
} catch (error) {
console.error("获取用户失败:", error);
return;
}
try {
const posts = await getPosts(user.id);
} catch (error) {
console.error("获取文章失败:", error);
return;
}
// ...
}
// 使用catch方法
async function fetchData() {
const response = await fetch("/api/data");
return response.json();
}
fetchData().catch(error => {
console.error("错误:", error);
});
// 等价于
async function fetchDataWithCatch() {
try {
const response = await fetch("/api/data");
return response.json();
} catch (error) {
console.error("错误:", error);
}
}
多个异步操作并行执行。
// 顺序执行(慢)
async function sequential() {
console.time("顺序");
const a = await fetch("/api/a");
const b = await fetch("/api/b");
const c = await fetch("/api/c");
console.timeEnd("顺序"); // 约3秒
return [a, b, c];
}
// 并行执行(快)
async function parallel() {
console.time("并行");
const [a, b, c] = await Promise.all([
fetch("/api/a"),
fetch("/api/b"),
fetch("/api/c")
]);
console.timeEnd("并行"); // 约1秒
return [a, b, c];
}
async function loadPage() {
// 并行加载多个数据
const [user, posts, settings] = await Promise.all([
fetch("/api/user").then(r => r.json()),
fetch("/api/posts").then(r => r.json()),
fetch("/api/settings").then(r => r.json())
]);
return { user, posts, settings };
}
// 带错误处理
async function loadPageSafe() {
try {
const results = await Promise.allSettled([
fetch("/api/user").then(r => r.json()),
fetch("/api/posts").then(r => r.json()),
fetch("/api/settings").then(r => r.json())
]);
const [user, posts, settings] = results.map(r =>
r.status === "fulfilled" ? r.value : null
);
return { user, posts, settings };
} catch (error) {
console.error("加载失败:", error);
}
}
async function complexFlow() {
// 第一步:获取用户
const user = await fetch("/api/user").then(r => r.json());
// 第二步:并行获取用户相关数据
const [posts, followers, following] = await Promise.all([
fetch(`/api/posts/${user.id}`).then(r => r.json()),
fetch(`/api/followers/${user.id}`).then(r => r.json()),
fetch(`/api/following/${user.id}`).then(r => r.json())
]);
return { user, posts, followers, following };
}
在循环中使用async/await。
// 顺序处理每个项目
async function processItems(items) {
for (const item of items) {
await processItem(item);
}
}
// 获取结果数组
async function fetchAllUrls(urls) {
const results = [];
for (const url of urls) {
const response = await fetch(url);
const data = await response.json();
results.push(data);
}
return results;
}
// 并行处理所有项目
async function processItemsParallel(items) {
await Promise.all(items.map(item => processItem(item)));
}
// 获取结果数组
async function fetchAllUrlsParallel(urls) {
const promises = urls.map(url =>
fetch(url).then(r => r.json())
);
return Promise.all(promises);
}
async function processItems(items) {
for (const item of items) {
await processItem(item);
}
}
// 带索引
async function processWithIndex(items) {
for (const [index, item] of items.entries()) {
console.log(`处理第${index}项`);
await processItem(item, index);
}
}
// 错误:forEach不会等待async
async function wrong() {
[1, 2, 3].forEach(async (item) => {
await delay(1000);
console.log(item); // 几乎同时输出
});
console.log("完成"); // 先输出
}
// 正确:使用for...of
async function correct() {
for (const item of [1, 2, 3]) {
await delay(1000);
console.log(item); // 每隔1秒输出
}
console.log("完成"); // 最后输出
}
// 或者并行
async function parallel() {
await Promise.all([1, 2, 3].map(async (item) => {
await delay(1000);
console.log(item);
}));
console.log("完成");
}
在模块顶层直接使用await。
// 模块顶层(ES模块)
// config.js
const response = await fetch("/api/config");
const config = await response.json();
export default config;
// 使用模块
import config from "./config.js";
console.log(config); // 配置已加载
// 动态导入模块
const module = await import("./heavy-module.js");
// 条件加载
const locale = await import(`./locales/${navigator.language}.js`);
// 依赖初始化
const database = await connectDatabase();
// 在不支持的环境中使用IIFE
(async () => {
const config = await fetch("/api/config").then(r => r.json());
console.log(config);
})();
// 或使用then
fetch("/api/config")
.then(r => r.json())
.then(config => {
console.log(config);
});
class ApiClient {
constructor(baseUrl) {
this.baseUrl = baseUrl;
}
async request(path, options = {}) {
const url = `${this.baseUrl}${path}`;
try {
const response = await fetch(url, {
headers: {
"Content-Type": "application/json",
...options.headers
},
...options
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
} catch (error) {
console.error("请求失败:", error);
throw error;
}
}
async get(path) {
return this.request(path);
}
async post(path, data) {
return this.request(path, {
method: "POST",
body: JSON.stringify(data)
});
}
}
// 使用
const api = new ApiClient("/api");
async function loadUser() {
const user = await api.get("/user/1");
console.log(user);
}
async function fetchWithRetry(url, options = {}, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
} catch (error) {
if (i === retries - 1) {
throw error;
}
console.log(`重试 ${i + 1}/${retries}`);
await delay(1000 * (i + 1)); // 递增延迟
}
}
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 使用
const data = await fetchWithRetry("/api/data", {}, 3);
async function limitConcurrency(tasks, limit = 3) {
const results = [];
const executing = [];
for (const task of tasks) {
const promise = Promise.resolve().then(() => task());
results.push(promise);
if (limit <= tasks.length) {
const exec = promise.then(() => {
executing.splice(executing.indexOf(exec), 1);
});
executing.push(exec);
if (executing.length >= limit) {
await Promise.race(executing);
}
}
}
return Promise.all(results);
}
// 使用
const urls = ["/api/1", "/api/2", "/api/3", "/api/4", "/api/5"];
const tasks = urls.map(url => () => fetch(url).then(r => r.json()));
const results = await limitConcurrency(tasks, 2); // 最多2个并发
掌握了Async/Await后,让我们继续学习:
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文寄语:async/await是Promise的语法糖,让异步代码看起来像同步代码,大大提高了代码可读性。在 db-w.cn,我们帮你掌握现代异步编程的最佳实践!