js之Promise

94 阅读3分钟

Promise 是 JavaScript 中处理异步操作的核心机制,通过状态管理和链式调用解决了回调地狱问题,提升了代码可读性和可维护性。以下是其核心要点和用法详解:


🔮 ​一、Promise 的本质与状态

  1. 定义
    Promise 是一个表示异步操作最终结果的对象,其状态不可逆:

    • ⏳ ​Pending(进行中)​​:初始状态。
    • ✅ ​Fulfilled(已成功)​​:异步操作成功完成,通过 resolve(value) 触发。
    • ❌ ​Rejected(已失败)​​:异步操作失败,通过 reject(reason) 或抛出异常触发 。
  2. 状态特性

    • 状态一旦从 Pending 变为 Fulfilled 或 Rejected,便不可再改变 。
    • 构造函数中若同时调用 resolvereject,仅第一次调用有效 。

⚙️ ​二、核心方法与使用

  1. 创建 Promise
    通过 new Promise() 传入执行器函数(同步执行):

    const promise = new Promise((resolve, reject) => {
      setTimeout(() => resolve('成功'), 1000); // 1秒后成功
    });
    
  2. ​**处理结果:then()catch()**​

    • then(onFulfilled, onRejected):注册成功/失败回调,返回新 Promise​ 支持链式调用 。

      promise.then(value => console.log(value)) // 输出"成功"
             .catch(err => console.error(err));
      
    • catch(onRejected):捕获错误,等同于 then(null, onRejected)

  3. 链式调用原理

    • 每次 then 返回新 Promise,其状态由回调返回值决定:

      • 返回非 Promise 值 → 新 Promise 成功(值为返回值)
      • 返回 Promise → 新 Promise 继承该 Promise 状态 。
      new Promise(resolve => resolve(10))
        .then(num => num * 2)       // 返回20 → 新Promise成功
        .then(num => Promise.reject('失败')) // 返回失败Promise
        .catch(err => console.log(err)); // 输出"失败"
      

🌟 ​三、静态方法与应用场景

  1. ​**Promise.all([p1, p2, ...])**​

    • 全部成功才成功​:返回所有结果的数组。
    • 任一失败则失败​:返回第一个失败原因 。
    Promise.all([fetch(url1), fetch(url2)])
      .then(results => console.log(results)) // [res1, res2]
      .catch(err => console.log('首个失败请求', err));
    
  2. ​**Promise.race([p1, p2, ...])**​

    • 首个完成的状态决定结果​:适用于超时控制 。
    const timeout = new Promise((_, reject) => 
      setTimeout(() => reject('超时'), 5000));
    Promise.race([fetch(url), timeout])
      .then(data => useData(data))
      .catch(() => fallback());
    
  3. 其他静态方法

    • Promise.resolve(value):返回成功状态的 Promise。
    • Promise.reject(reason):返回失败状态的 Promise 。
    • Promise.allSettled([p1, p2]):等待所有完成,返回状态结果数组(ES2020) 。

🛡️ ​四、错误处理与最佳实践

  1. 统一错误捕获
    使用 catch 捕获链式调用中任意环节的错误:

    fetchData()
      .then(process)
      .then(updateUI)
      .catch(err => showError(err)); // 统一处理所有错误
    
  2. 避免常见陷阱

    • 回调中抛错​:自动触发 catch(等效于 reject)。
    • 未捕获的拒绝​:使用 .catch()process.on('unhandledRejection')(Node.js)。

⚡ ​五、底层原理与微任务

  • 事件循环机制​:Promise 回调属于微任务​(Microtask),优先级高于宏任务(如 setTimeout)。
  • 状态变更流程​:
    resolve/reject → 将回调推入微任务队列 → 当前宏任务结束后立即执行 。

💎 ​总结与最佳实践

  • 适用场景​:

    • 替代回调嵌套(如多层网络请求)。
    • 并行任务管理(Promise.all)或竞态任务(Promise.race)。
  • 核心原则​:

    1. 使用链式调用替代嵌套。
    2. 始终用 catch 捕获错误。
    3. 避免在 then 中混合同步/异步操作(用 Promise.resolve 包装同步值)。
  • 进阶工具​:
    async/await 是 Promise 的语法糖,提供更同步化的写法 。

通过合理使用 Promise 的状态机模型、链式调用和静态方法,可显著提升异步代码的健壮性和可读性。实践中可结合 async/await 进一步简化复杂逻辑 。