Z
ZHANK
异步编程

Promise 基础

掌握 Promise 创建、then/catch、链式调用

Promise 基础

回调函数的问题是"回调地狱"——嵌套越来越深,错误处理分散,流程难以控制。Promise 用链式调用解决了这个痛点,是 JavaScript 异步编程的基础。

学完本章你将: 理解 Promise 的状态机制、then/catch 链式调用、静态方法。


Promise 是什么

Promise 就是一个承诺:"我将来会给你一个结果,要么成功要么失败"。它有且只有三种状态,一旦确定永不改变。

pending(等待中)
    ↙        ↘
fulfilled(成功)  rejected(失败)
javascript
// 创建一个 Promise:传入的函数立即执行
let promise = new Promise((resolve, reject) => {
    // setTimeout 模拟异步操作(比如网络请求)
    setTimeout(() => {
        let success = true;
        if (success) {
            resolve("操作成功!");     // 成功 → 状态变为 fulfilled
        } else {
            reject(new Error("失败!")); // 失败 → 状态变为 rejected
        }
    }, 1000);
});

// resolve/reject 只能调一个,调完状态就锁死,后面的 resolve/reject 无效

then / catch / finally —— 处理结果

.then() 接收两个函数(成功回调和失败回调),但通常只用第一个,失败交给 .catch()

javascript
promise
    .then(result => {                  // fulfilled 时执行
        console.log("成功:", result);
        return result.toUpperCase();   // 返回的值会包装成新 Promise
    })
    .then(upper => {                   // 上一个 then 的返回值
        console.log("大写:", upper);
    })
    .catch(error => {                  // 任意位置 rejected 都会跳到这里
        console.error("出错了:", error.message);
    })
    .finally(() => {                   // 无论如何都执行
        console.log("清理工作");
    });

💡 关键: .then() 永远返回新的 Promise,所以可以无限链下去。这就是"链式调用"——比回调嵌套清晰得多。


链式调用 —— 解决回调地狱

javascript
// ❌ 回调地狱
getUser(1, (err, user) => {
    getPosts(user.id, (err, posts) => {
        getComments(posts[0].id, (err, comments) => { /* … */ });
    });
});

// ✅ Promise 链
getUser(1)
    .then(user => getPosts(user.id))
    .then(posts => getComments(posts[0].id))
    .then(comments => console.log(comments))
    .catch(err => console.error("哪儿出错都到这", err));

静态方法

javascript
// Promise.resolve / reject —— 快速创建
Promise.resolve(42).then(n => console.log(n));   // 42
Promise.reject("错").catch(e => console.log(e)); // "错"

// Promise.all —— 全部成功才成功(并发执行)
Promise.all([fetch("/api/users"), fetch("/api/posts")])
    .then(([users, posts]) => { /* 两个都拿到了 */ })
    .catch(err => { /* 任意一个失败 */ });

// Promise.allSettled —— 等全部完成,不管成败
Promise.allSettled([Promise.resolve(1), Promise.reject("err")])
    .then(results => results.forEach(r => console.log(r.status)));

// Promise.race —— 第一个完成的(不管成败)
Promise.race([fetch("/fast"), timeout(5000)]);

// Promise.any —— 第一个成功的(ES2021)
Promise.any([fetch("/mirror1"), fetch("/mirror2")]);

function getUser(id) { return new Promise((resolve) => { setTimeout(() => resolve({ id, name: "Alice" }), 500); }); }

function getPosts(userId) { return new Promise((resolve) => { setTimeout(() => resolve(["post1", "post2"]), 500); }); }

getUser(1) .then(user => { console.log("用户:", user.name); return getPosts(user.id); // 返回新 Promise }) .then(posts => { console.log("帖子:", posts); }) .catch(err => console.error(err));


---

## 静态方法

```javascript
// Promise.resolve
Promise.resolve(42).then(n => console.log(n)); // 42

// Promise.reject
Promise.reject("失败").catch(e => console.log(e));

// Promise.all —— 全部成功才成功
Promise.all([
    fetch("/api/user"),
    fetch("/api/posts"),
    fetch("/api/comments"),
]).then(([user, posts, comments]) => {
    console.log("全部完成!");
}).catch(err => {
    console.log("任意一个失败 -> catch");
});

// Promise.allSettled —— 等全部完成(不管成功失败)
Promise.allSettled([
    Promise.resolve(1),
    Promise.reject("err"),
    Promise.resolve(3),
]).then(results => {
    results.forEach(r => console.log(r.status)); // fulfilled, rejected, fulfilled
});

// Promise.race —— 第一个完成的
Promise.race([
    fetch("/api/fast"),
    new Promise((_, reject) => setTimeout(() => reject("超时"), 5000)),
]).then(r => r.json());

// Promise.any —— 第一个成功的(ES2021)
Promise.any([
    Promise.reject("err1"),
    Promise.resolve("ok"),
]).then(r => console.log(r)); // "ok"