通俗版Promise解释

通俗版Promise解释

首先要理解前端的同步异步任务流程

同步 vs 异步任务

同步任务(排队买奶茶)

1
2
3
4
5
6
7
// 你站在柜台前干等,不做其他事
console.log("1. 点单:我要珍珠奶茶");
console.log("2. 等店员制作...(干等5秒)");
// 模拟同步等待
const start = Date.now();
while (Date.now() - start < 5000) {} // 直接阻断后面的进程,阻塞5秒
console.log("3. 拿到奶茶,开心喝!");

异步任务(外卖通知)

1
2
3
4
5
6
console.log("1. 手机下单奶茶");
// 异步操作:下单后先做其他事,等通知
setTimeout(() => {
console.log("3. 外卖员通知:奶茶到啦!");
}, 5000); // 5秒后才触发回调,不阻塞主进程
console.log("2. 下单成功,先去打游戏~");

输出顺序

1
2
3
1. 手机下单奶茶  
2. 下单成功,先去打游戏~
3. 外卖员通知:奶茶到啦!

Promise

**可以把 Promise 想象成一张 订餐时的订单小票 **你点了一份外卖(发起一个异步操作),这时候服务员不会让你干等着,而是给你一张订单小票(Promise对象),告诉你:“餐好了会通知你”。


通俗版解释:

  1. 下单(Pending状态)
    • **你点了餐,但饭还没做好 → **new Promise() 创建时处于 进行中(Pending)
    • 此时你(代码)可以继续做其他事(比如玩手机),不用一直盯着厨房。(异步)
  2. 餐好了(Fulfilled状态)
    • **厨房通知你:“餐好了,来取吧!” → Promise **成功(Resolved)
    • **你拿到饭后开始吃 → 用 **.then() 处理成功的结果:
      1
      order.then(food => eat(food)); // 拿到饭就吃
  3. 餐出问题了(Rejected状态)
    • **厨房说:“抱歉,没食材了” → Promise **失败(Rejected)
    • **你决定泡面 → 用 **.catch() 处理失败:
      1
      order.catch(error => eatInstantNoodles()); // 失败就吃泡面
  4. 无论如何都要收拾桌子(Finally)
    • **不管吃没吃到外卖,你都要擦桌子 → **.finally()
      1
      order.finally(() => cleanTable()); // 无论成败都执行

为什么比 “回调函数” 更好?

  • 回调地狱(Callback Hell)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    // 传统回调写法
    function orderMilkTea(callback) {
    setTimeout(() => {
    console.log("1. 拿到基础奶茶");
    callback(null, "🍵基础奶茶");
    }, 1000);
    }

    function addPearl(tea, callback) {
    setTimeout(() => {
    console.log("2. 加珍珠");
    callback(null, tea + " + 🎱珍珠");
    }, 1000);
    }

    function addCheeseFoam(tea, callback) {
    setTimeout(() => {
    console.log("3. 加奶盖");
    callback(null, tea + " + 🧀奶盖");
    }, 1000);
    }

    // 使用回调地狱
    orderMilkTea((error, tea) => {
    if (error) {
    console.log("失败:", error);
    } else {
    addPearl(tea, (error, teaWithPearl) => {
    if (error) {
    console.log("失败:", error);
    } else {
    addCheeseFoam(teaWithPearl, (error, finalTea) => {
    if (error) {
    console.log("失败:", error);
    } else {
    console.log("最终奶茶:", finalTea);
    }
    });
    }
    });
    }
    });
  • Promise链式调用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    // 用Promise包装异步操作
    function orderMilkTea() {
    return new Promise((resolve) => {
    setTimeout(() => {
    console.log("1. 拿到基础奶茶");
    resolve("🍵基础奶茶");
    }, 1000);
    });
    }

    function addPearl(tea) {
    return new Promise((resolve) => {
    setTimeout(() => {
    console.log("2. 加珍珠");
    resolve(tea + " + 🧋珍珠");
    }, 1000);
    });
    }

    function addCheeseFoam(tea) {
    return new Promise((resolve) => {
    setTimeout(() => {
    console.log("3. 加奶盖");
    resolve(tea + " + 🧀奶盖");
    }, 1000);
    });
    }

    // 链式调用
    orderMilkTea()
    .then(tea => addPearl(tea))
    .then(teaWithPearl => addCheeseFoam(teaWithPearl))
    .then(finalTea => {
    console.log("最终奶茶:", finalTea);
    })
    .catch(error => {
    console.log("失败:", error);
    })
    .finally(() => {
    console.log("流程结束,清理操作");
    });

一句话总结:

**Promise 就是一张 ****“未来事件保证书”**,告诉程序:“别干等,先忙你的,事情成了或黄了,我都会给你个交代!”