对Promise的理解

4 阅读4分钟

Promise 是什么?​

简单来说,​Promise 是 JavaScript 用来处理异步操作的一个“承诺”​

想象一下:

  • 你去餐厅点餐,服务员不会让你干等着,而是给你一个取餐号​(Promise),告诉你:“餐好了会通知你”。
  • 这个号(Promise)代表未来的结果,可能是成功(拿到餐),也可能是失败(餐卖完了)。

1. 为什么需要 Promise?​

在 Promise 之前,JavaScript 用回调函数(Callback)​处理异步,比如:

getData(function(data) {  // 成功回调
    processData(data, function(result) {  // 嵌套回调
        saveData(result, function() {  // 又一层回调
            console.log("Done!");
        });
    });
});

问题​:

  • 回调地狱(Callback Hell)​​:代码嵌套太深,像“金字塔”,难读难维护。
  • 错误处理麻烦​:每个回调都要单独处理错误。

👉 ​Promise 的解决方案​:
.then() 链式调用,让代码变“扁平”,更接近同步代码的写法。


2. Promise 的三种状态

Promise 就像一个“状态机”,有 ​3 种状态​:

状态说明比喻
Pending进行中,还没结果“餐还没做好,等着吧”
Fulfilled成功,有结果了(调用 resolve“餐好了,快来拿!”
Rejected失败,出错了(调用 reject“抱歉,餐卖完了”

⚠️ 注意​:

  • 状态一旦改变,就不能再变​(比如从 fulfilled 变成 rejected 是不行的)。
  • 如果没监听错误(.catch()),控制台会报 UnhandledPromiseRejectionWarning(未处理的 Promise 拒绝)。

3. 基本用法:创建 Promise

const promise = new Promise((resolve, reject) => {
    // 这里是异步操作,比如 AJAX 请求、定时器等
    if (/* 成功 */) {
        resolve("成功的结果");  // 状态变为 fulfilled
    } else {
        reject("失败的原因");   // 状态变为 rejected
    }
});

例子​:模拟一个点餐 Promise

function orderFood() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const isSuccess = Math.random() > 0.5;  // 50% 概率成功
            if (isSuccess) {
                resolve("🍔 汉堡做好了!");
            } else {
                reject("❌ 汉堡卖完了!");
            }
        }, 2000);  // 2秒后出结果
    });
}

​**4. 使用 Promise:.then().catch()**​

拿到 Promise 后,用 .then() 处理成功,.catch() 处理失败:

orderFood()
    .then((food) => {
        console.log(food);  // "🍔 汉堡做好了!"
    })
    .catch((error) => {
        console.log(error); // "❌ 汉堡卖完了!"
    });

👉 关键点​:

  • .then() 可以链式调用,避免回调地狱。
  • .catch() 会捕获前面所有 .then() 里的错误

链式调用示例​:

orderFood()
    .then((food) => {
        console.log(food);
        return "🍟 加一份薯条";  // 返回一个新值,传给下一个 .then()
    })
    .then((sideDish) => {
        console.log(sideDish);  // "🍟 加一份薯条"
    })
    .catch((error) => {
        console.log("出错啦:", error);
    });

5. 高级用法

​(1) Promise.all() – 等所有 Promise 完成

const p1 = Promise.resolve("任务1");
const p2 = Promise.resolve("任务2");
const p3 = new Promise((resolve) => setTimeout(() => resolve("任务3"), 1000));

Promise.all([p1, p2, p3])
    .then((results) => {
        console.log(results);  // ["任务1", "任务2", "任务3"]
    })
    .catch((error) => {
        console.log("有一个失败了", error);
    });

特点​:

  • 所有 Promise 都成功,才返回结果数组。
  • ​**有一个失败,立即进入 .catch()**​(不会等其他的)。

适用场景​:

  • 同时发多个请求,等全部完成后处理数据。

​(2) Promise.race() – 谁快用谁

const p1 = new Promise((resolve) => setTimeout(() => resolve("任务1"), 2000));
const p2 = new Promise((resolve) => setTimeout(() => resolve("任务2"), 1000));

Promise.race([p1, p2])
    .then((result) => {
        console.log(result);  // "任务2"(因为 p2 更快)
    });

特点​:

  • 第一个完成的 Promise(无论成功/失败)决定结果。

适用场景​:

  • 请求超时控制(比如 3 秒内没响应就报错)。

​(3) Promise.finally() – 无论成功失败都执行

orderFood()
    .then((food) => console.log(food))
    .catch((error) => console.log(error))
    .finally(() => {
        console.log("无论如何,餐厅关门了");
    });

特点​:

  • 类似 try/catch/finally,适合清理操作(比如关闭加载动画)。

6. 常见误区

❌ ​误区 1:忘记 return


// 错误写法!第二个 then 拿不到 "🍟"
orderFood()
    .then((food) => {
        console.log(food);
        "🍟 加一份薯条";  // 没写 return!
    })
    .then((sideDish) => {
        console.log(sideDish);  // undefined
    });

✅ ​正确写法​:

javascript
javascript
复制
.then((food) => {
    console.log(food);
    return "🍟 加一份薯条";  // 必须 return!
})

❌ ​误区 2:错误处理不完整

javascript
javascript
复制
// 错误写法!如果 then 里出错,catch 抓不到
orderFood()
    .then((food) => {
        throw new Error("吃到虫子了!");  // 这里会报错
    })
    .catch((error) => {
        console.log(error);  // 能捕获
    });

✅ ​正确写法​:
确保每个可能出错的地方都有 .catch()


7. 总结:Promise 的核心价值

  1. 解决回调地狱​ → 用 .then() 链式调用,代码更清晰。
  2. 更好的错误处理​ → 用 .catch() 统一捕获错误。
  3. 支持并发控制​ → Promise.all / Promise.race 管理多个异步任务。
  4. 更接近同步写法​ → 让异步代码更容易理解和维护。

最终比喻

Promise 就像外卖订单​:

  • 你下单(new Promise
  • 餐厅接单(pending
  • 要么成功送到(resolve.then()
  • 要么失败退款(reject.catch()
  • 无论如何,最后清理餐桌(.finally()

有了 Promise,异步代码再也不是“一团乱麻”,而是清晰可控的流程​!