author: 专注前端开发,分享JavaScript干货
title: JavaScript入门⑧|Promise与async_await,彻底搞懂异步编程
update: 2026-04-28
tags: JavaScript,Promise,async,await,异步,回调地狱,then,catch,前端入门

作者:专注前端开发,分享JavaScript干货
更新时间:2026年4月
适合人群:掌握JS基础,想彻底理解异步编程的同学


前言:同步与异步

JavaScript是单线程的,同步代码会阻塞后面代码的执行。

异步:不等待耗时操作完成,先往下执行,等操作好了再通知你。

// 同步:排队执行
console.log("1");
console.log("2");
console.log("3");

// 异步:不等结果,先往下走
console.log("1");
setTimeout(() => console.log("3"), 1000);
console.log("2"); // 这行先执行
// 输出顺序:1 → 2 → 3

一、回调函数的困境

// 老式回调:多层嵌套后变成"回调地狱"
getUser(userId, function(user) {
    getOrders(user.id, function(orders) {
        getOrderDetails(orders[0].id, function(details) {
            getProduct(details.productId, function(product) {
                console.log(product);
            });
        });
    });
});

问题:嵌套太深、错误处理困难、代码难维护。


二、Promise 基础

2.1 创建Promise

// Promise有三种状态:pending(进行中)、fulfilled(成功)、rejected(失败)
const promise = new Promise((resolve, reject) => {
    // 异步操作
    setTimeout(() => {
        const success = true;
        if (success) {
            resolve("操作成功!"); // 成功时调用resolve
        } else {
            reject(new Error("操作失败!")); // 失败时调用reject
        }
    }, 1000);
});

console.log(promise); // Promise { <pending> }

2.2 then / catch / finally

promise
    .then(result => {
        console.log(result); // "操作成功!"
        return "第二次成功";
    })
    .then(result => {
        console.log(result); // "第二次成功"
    })
    .catch(error => {
        console.error(error.message); // 处理错误
    })
    .finally(() => {
        console.log("无论成功失败都会执行"); // 做清理工作
    });

2.3 Promise链式调用

// 用Promise改写回调地狱,扁平化
getUser(userId)
    .then(user => getOrders(user.id))
    .then(orders => getOrderDetails(orders[0].id))
    .then(details => getProduct(details.productId))
    .then(product => console.log(product))
    .catch(error => console.error(error.message));

三、Promise静态方法

3.1 Promise.all(全部成功才成功)

// 同时发送多个请求,等全部完成
const promise1 = fetchUser();
const promise2 = fetchPosts();
const promise3 = fetchComments();

Promise.all([promise1, promise2, promise3])
    .then(([user, posts, comments]) => {
        console.log("用户:", user);
        console.log("帖子:", posts);
        console.log("评论:", comments);
    })
    .catch(error => {
        console.error("某个请求失败了:", error);
    });

3.2 Promise.allSettled(全部完成,无论成功失败)

// 想知道每个请求的结果,不管成功还是失败
Promise.allSettled([
    fetchUser(),
    fetchPosts(),
    fetchFailingRequest() // 这个会失败
]).then(results => {
    results.forEach((result, index) => {
        if (result.status === "fulfilled") {
            console.log(`请求${index}成功:`, result.value);
        } else {
            console.log(`请求${index}失败:`, result.reason);
        }
    });
});

3.3 Promise.race(返回最快的那个)

// 哪个先完成就用哪个(常用于超时控制)
const timeoutPromise = new Promise((_, reject) =>
    setTimeout(() => reject(new Error("超时!")), 5000)
);

const fetchPromise = fetch("https://api.example.com/data");

Promise.race([fetchPromise, timeoutPromise])
    .then(data => console.log("获取成功:", data))
    .catch(error => console.error("失败:", error.message));

3.4 Promise.any(返回第一个成功的)

// 多个接口,只要有一个成功就行
Promise.any([
    fetch("https://api1.example.com"),
    fetch("https://api2.example.com"),
    fetch("https://api3.example.com")
]).then(result => console.log("最快的成功结果:", result));

四、async / await(同步写法写异步)

4.1 基本用法

// async函数自动返回Promise
async function fetchData() {
    // await暂停函数执行,等待Promise解决
    const result = await someAsyncFunction();
    console.log(result);
    return result;
}

// 调用
fetchData().then(result => console.log("最终结果", result));

4.2 实战:顺序请求与并行请求

// 模拟异步函数
const delay = (ms, value) =>
    new Promise(resolve => setTimeout(() => resolve(value), ms));

// 顺序执行(串行)
async function sequential() {
    const start = Date.now();
    const r1 = await delay(1000, "结果1");
    const r2 = await delay(1000, "结果2");
    const r3 = await delay(1000, "结果3");
    const elapsed = Date.now() - start;
    console.log(`顺序执行耗时:${elapsed}ms`); // ~3000ms
    return [r1, r2, r3];
}

// 并行执行(Promise.all + await)
async function parallel() {
    const start = Date.now();
    const promises = [
        delay(1000, "结果1"),
        delay(1000, "结果2"),
        delay(1000, "结果3")
    ];
    const results = await Promise.all(promises);
    const elapsed = Date.now() - start;
    console.log(`并行执行耗时:${elapsed}ms`); // ~1000ms
    return results;
}

async function main() {
    console.log("--- 顺序 ---");
    await sequential();
    console.log("--- 并行 ---");
    await parallel();
}
main();

4.3 错误处理

async function fetchUserData(id) {
    try {
        // 可能失败的代码
        const user = await fetchUser(id);
        const posts = await fetchPosts(user.id);

        // 手动的错误检查
        if (!user) {
            throw new Error("用户不存在");
        }

        return { user, posts };
    } catch (error) {
        console.error("获取数据失败:", error.message);
        return null; // 返回默认值
    } finally {
        console.log("请求完成,无论成功失败");
    }
}

// 并行请求的错误处理
async function fetchMultiple() {
    try {
        const [user, posts, comments] = await Promise.all([
            fetchUser(1),
            fetchPosts(1),
            fetchComments(1)
        ]);
        return { user, posts, comments };
    } catch (error) {
        console.error("某个请求失败了:", error.message);
        throw error; // 或者重新抛出
    }
}

五、知识卡

方法 说明
new Promise() 创建Promise
.then() Promise成功后执行
.catch() Promise失败后执行
.finally() 无论成功失败都执行
Promise.all() 全部成功才成功
Promise.allSettled() 全部完成,保留所有结果
Promise.race() 返回最快的
Promise.any() 返回第一个成功的
async 声明异步函数
await 等待Promise解决

六、课后作业

  1. Promise 封装一个 delay 函数,模拟延迟
  2. 实现一个函数,同时请求3个接口,返回所有成功的结果,忽略失败的
  3. async/await 重写一个多层嵌套的回调函数

有问题欢迎评论区留言,大家一起讨论!


标签:JavaScript | Promise | async | await | 异步编程 | 回调地狱 | then | catch

更多推荐