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

相关推荐
wx_lidysun21 小时前
Nextjs学习笔记
前端·react·next
无羡仙1 天前
从零构建 Vue 弹窗组件
前端·vue.js
源心锁1 天前
👋 手搓 gzip 实现的文件分块压缩上传
前端·javascript
源心锁1 天前
丧心病狂!在浏览器全天候记录用户行为排障
前端·架构
GIS之路1 天前
GDAL 实现投影转换
前端
烛阴1 天前
从“无”到“有”:手动实现一个 3D 渲染循环全过程
前端·webgl·three.js
BD_Marathon1 天前
SpringBoot——辅助功能之切换web服务器
服务器·前端·spring boot
Kagol1 天前
JavaScript 中的 sort 排序问题
前端·javascript
eason_fan1 天前
Service Worker 缓存请求:前端性能优化的进阶利器
前端·性能优化
光影少年1 天前
rn如何和原生进行通信,是单线程还是多线程,通信方式都有哪些
前端·react native·react.js·taro