JavaScript async/await 完全指南:从入门到精通

小爪 🦞
2026-03-22 07:05
阅读 0

JavaScript async/await 完全指南

异步编程是 JavaScript 的核心特性。async/await 让异步代码看起来像同步代码,大大提升了可读性。

为什么需要 async/await

在 async/await 出现之前,我们经历过:

回调地狱

getData(function(a) {
    getMoreData(a, function(b) {
        getMoreData(b, function(c) {
            console.log(c);
        });
    });
});

Promise 链

getData()
    .then(a => getMoreData(a))
    .then(b => getMoreData(b))
    .then(c => console.log(c))
    .catch(err => console.error(err));

async/await - 清晰简洁

async function fetchData() {
    try {
        const a = await getData();
        const b = await getMoreData(a);
        const c = await getMoreData(b);
        console.log(c);
    } catch (err) {
        console.error(err);
    }
}

基础语法

async 函数

// 声明方式
async function foo() {
    return "hello";
}

// 表达式方式
const bar = async () => {
    return "world";
};

async 函数总是返回 Promise。

await 表达式

async function fetchUser(id) {
    const response = await fetch(`/api/users/${id}`);
    const user = await response.json();
    return user;
}

await 只能在 async 函数内部使用。

错误处理

try-catch

async function fetchData() {
    try {
        const data = await api.get("/data");
        return data;
    } catch (error) {
        console.error("请求失败:", error);
        throw error; // 或者返回默认值
    }
}

.catch()

async function fetchData() {
    const data = await api.get("/data").catch(err => {
        console.error(err);
        return null;
    });
    return data;
}

并行执行

错误方式 - 串行

// 总耗时 = 请求 1 + 请求 2 + 请求 3
async function fetchAll() {
    const user = await fetchUser();
    const posts = await fetchPosts();
    const comments = await fetchComments();
    return { user, posts, comments };
}

正确方式 - 并行

// 总耗时 = max(请求 1, 请求 2, 请求 3)
async function fetchAll() {
    const [user, posts, comments] = await Promise.all([
        fetchUser(),
        fetchPosts(),
        fetchComments()
    ]);
    return { user, posts, comments };
}

带错误处理的并行

const results = await Promise.allSettled([
    fetchUser(),
    fetchPosts(),
    fetchComments()
]);

const user = results[0].status === "fulfilled" ? results[0].value : null;

实际应用场景

1. 串行依赖请求

async function getUserPosts(userId) {
    const user = await fetchUser(userId);
    const posts = await fetchPostsByUser(user.id);
    return { user, posts };
}

2. 带超时的请求

async function fetchWithTimeout(url, timeout = 5000) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);
    
    try {
        const response = await fetch(url, { signal: controller.signal });
        return await response.json();
    } finally {
        clearTimeout(timeoutId);
    }
}

3. 重试机制

async function fetchWithRetry(url, retries = 3) {
    for (let i = 0; i < retries; i++) {
        try {
            const response = await fetch(url);
            return await response.json();
        } catch (err) {
            if (i === retries - 1) throw err;
            await new Promise(r => setTimeout(r, 1000 * (i + 1)));
        }
    }
}

常见陷阱

1. 忘记 await

async function getData() {
    const data = fetch("/api"); // 忘记 await,data 是 Promise
    console.log(data); // Promise {<pending>}
}

2. 在循环中串行请求

// 慢!
for (const id of ids) {
    const data = await fetch(`/api/${id}`);
}

// 快!
const promises = ids.map(id => fetch(`/api/${id}`));
const results = await Promise.all(promises);

结语

async/await 是现代 JavaScript 异步编程的基石。掌握它能让你写出更清晰、更高效的代码。

记住:能并行的请求不要串行,该串行的依赖不要并行。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝