Promise 核心知识点(非基础)

大家好,我是有一点想法的thinkmars,目前在准备面试与工作,借着间隙时间学习复习,写一点基础文章,欢迎想找工作的人与我一起学习,一起讨饭吃~


Promise的出现是异步编程的革命,自问世以后,前端再也离不开它。

一、Promise 执行机制核心原理

  1. Event Loop 与微任务队列

    • Promise 回调属于微任务(Microtask),与宏任务(Macrotask)的区别
    • 代码执行顺序分析:setTimeout vs Promise.then() 的执行优先级
    • 示例分析:console.log(1); Promise.resolve().then(()=>console.log(2)); console.log(3);
  2. Promise 链式调用原理

    • then() 方法返回新 Promise 的规则:
      • 返回普通值 → 触发新 Promise 的 resolve
      • 返回 Promise → 直接继承其状态
      • 抛出错误 → 触发新 Promise 的 reject
    • 链式调用中断场景分析:中间某个 then() 抛出错误如何传递?

二、Promise 状态流转与代码路径

  1. 状态变化关键逻辑

    • resolve() 触发后,后续 then() 中的回调进入微任务队列
    • reject() 触发后,优先寻找最近的 catch()then(onFulfilled, onRejected) 的第二个参数
    • 状态固化后不可变:即使再次调用 resolve/reject 无效
  2. 代码路径分析(高频考题)

    javascript 复制代码
    new Promise((resolve, reject) => {
      console.log(1);
      resolve(2);
      console.log(3);
    })
    .then(val => {
      console.log(val);
      return val * 2;
    })
    .then(val => {
      console.log(val);
      throw new Error('test');
    })
    .catch(err => {
      console.log(err.message);
      return 100;
    })
    .then(val => console.log(val));
    • 输出顺序分析:1 → 3 → 2 → 4 → 'test' → 100
    • 关键点:同步代码立即执行,then/catch 回调异步执行

三、错误处理关键技巧

  1. catch 的穿透性

    • 错误会沿着链式调用传递,直到被 catch 捕获
    • 示例:若中间某个 then() 没有错误处理,错误会跳过后续 then() 的第一个参数
  2. reject 的两种写法

    • 显式调用 reject()
    • 抛出异常:throw new Error('msg')(等同于 reject
  3. 全局异常捕获

    • window.addEventListener('unhandledrejection', callback) 处理未捕获的 Promise 错误

四、高阶 API 使用场景

  1. Promise.all vs Promise.allSettled

    • all: 全部成功时返回结果数组,任一失败立即拒绝
    • allSettled: 始终等待所有 Promise 完成,返回状态描述对象
    • 适用场景对比(如批量请求是否允许部分失败)
  2. Promise.race 竞速场景

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

    • 超时控制实战代码:

      javascript 复制代码
      const timeout = (ms) => 
        new Promise((_, reject) => 
          setTimeout(() => reject(new Error('Timeout')), ms)
        );
      
      Promise.race([fetchData(), timeout(3000)])
        .then(data => console.log(data))
        .catch(err => console.log(err));
  3. Promise.any(ES2021)

    • 第一个成功的 Promise 决定结果,全部失败时抛出 AggregateError

五、常见陷阱与面试题

  1. 嵌套 Promise 问题

    • 反模式:在 then() 中嵌套 new Promise(应使用链式调用扁平化)
  2. 值穿透(Value Penetration)

    javascript 复制代码
    Promise.resolve(1)
      .then(Promise.resolve(2))  // 参数不是函数!
      .then(console.log);        // 输出 1
    • 原因:then() 的参数必须为函数,否则发生值穿透
  3. 同步代码中的错误

    javascript 复制代码
    new Promise((resolve, reject) => {
      throw new Error('sync error');  // 同步错误直接触发 reject
    }).catch(err => console.log(err));

六、Async/Await 与 Promise 的关系

  1. 本质是语法糖

    • async 函数返回 Promise,await 相当于 then() 的链式调用
    • 错误处理:try/catch 捕获 await 后的 Promise reject
  2. 执行顺序对比

    • 分析 async/await 与普通 Promise 链的微任务队列差异

七、实战代码分析训练

  1. 混合宏任务/微任务执行顺序

    javascript 复制代码
    setTimeout(() => console.log(1), 0);
    Promise.resolve().then(() => console.log(2));
    console.log(3);
    // 输出顺序:3 → 2 → 1
  2. 复杂链式调用+错误处理

    javascript 复制代码
    Promise.resolve()
      .then(() => { throw new Error('err1'); })
      .catch(() => console.log('catch1'))
      .then(() => console.log('then1'))
      .catch(() => console.log('catch2'));
    // 输出:catch1 → then1
相关推荐
亭台烟雨中3 分钟前
【前端记事】关于electron的入门使用
前端·javascript·electron
泯泷17 分钟前
「译」解析 JavaScript 中的循环依赖
前端·javascript·架构
抹茶san19 分钟前
前端实战:从 0 开始搭建 pnpm 单一仓库(1)
前端·架构
Senar1 小时前
Web端选择本地文件的几种方式
前端·javascript·html
南客先生1 小时前
互联网大厂Java面试:RocketMQ、RabbitMQ与Kafka的深度解析
java·面试·kafka·rabbitmq·rocketmq·消息中间件
烛阴1 小时前
UV Coordinates & Uniforms -- OpenGL UV坐标和Uniform变量
前端·webgl
姑苏洛言1 小时前
扫码小程序实现仓库进销存管理中遇到的问题 setStorageSync 存储大小限制错误解决方案
前端·后端
烛阴1 小时前
JavaScript 的 8 大“阴间陷阱”,你绝对踩过!99% 程序员崩溃瞬间
前端·javascript·面试