js之Promise

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


🔮 ​一、Promise 的本质与状态

  1. 定义

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

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

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

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

  1. 创建 Promise

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

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

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

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

  3. 链式调用原理

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

      • 返回非 Promise 值 → 新 Promise 成功(值为返回值)
      • 返回 Promise → 新 Promise 继承该 Promise 状态 。
      typescript 复制代码
      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, ...])**​

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

    • 首个完成的状态决定结果:适用于超时控制 。
    typescript 复制代码
    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 捕获链式调用中任意环节的错误:

    scss 复制代码
    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 进一步简化复杂逻辑 。

相关推荐
毕设源码-邱学长4 小时前
【开题答辩全过程】以 基于VUE的藏品管理系统的设计与实现为例,包含答辩的问题和答案
前端·javascript·vue.js
用户28907942162715 小时前
Spec-Kit应用指南
前端
酸菜土狗5 小时前
🔥 手写 Vue 自定义指令:实现内容区拖拽调整大小(超实用)
前端
ohyeah5 小时前
深入理解 React Hooks:useState 与 useEffect 的核心原理与最佳实践
前端·react.js
Cache技术分享5 小时前
275. Java Stream API - flatMap 操作:展开一对多的关系,拉平你的流!
前端·后端
apollo_qwe6 小时前
前端缓存深度解析:从基础到进阶的实现方式与实践指南
前端
周星星日记6 小时前
vue中hash模式和history模式的区别
前端·面试
Light606 小时前
Vue 高阶优化术:v-bind 与 v-on 的实战妙用与思维跃迁
前端·低代码·vue3·v-bind·组件封装·v-on·ai辅助开发
周星星日记6 小时前
5.为什么vue中使用query可以保留参数
前端·vue.js
lebornjose6 小时前
javascript - webgl中绑定(bind)缓冲区的逻辑是什么?
前端·webgl