Promise状态和方法都有哪些,以及实现原理

很好 👌 你问的是 Promise 的状态、方法,以及实现原理。我帮你拆成三部分来讲:


一、Promise 的状态

Promise 内部有 三种状态[[PromiseState]]):

  1. pending(进行中):初始状态,既没有被 fulfilled,也没有被 rejected。
  2. fulfilled (已成功):操作成功完成,并返回一个值(用 resolve 触发)。
  3. rejected (已失败):操作失败,并返回失败原因(用 reject 触发)。

⚠️ 特点:

  • 状态 只能从 pending → fulfilledpending → rejected ,一旦变化就 不可逆
  • 成功和失败只能发生一次,后续调用 resolve / reject 不会再改变状态。

二、Promise 的方法

1. 实例方法

  • then(onFulfilled, onRejected)

    • 注册成功和失败的回调。
    • 返回一个新的 Promise(可链式调用)。
    • 如果 onFulfilled / onRejected 返回值是 Promise,会进行 状态递归解析
  • catch(onRejected)

    • 相当于 .then(undefined, onRejected)
    • 用于错误捕获。
  • finally(onFinally)

    • 无论成功/失败都会执行。
    • 不会改变链式调用的结果,只做副作用处理。

2. 静态方法

  • Promise.resolve(value)

    • 返回一个 fulfilled 状态的 Promise。
    • 如果参数本身是 Promise,直接返回。
  • Promise.reject(reason)

    • 返回一个 rejected 状态的 Promise。
  • Promise.all(iterable)

    • 并行执行多个 Promise,所有都成功才成功,否则第一个失败就失败。
  • Promise.allSettled(iterable)

    • 等待所有 Promise 执行完,不管成功/失败,返回每个结果的数组。
  • Promise.race(iterable)

    • 谁先有结果(成功或失败)就返回谁的结果。
  • Promise.any(iterable)

    • 只要有一个成功就返回成功,如果全部失败则返回 AggregateError

三、Promise 实现原理

Promise 的核心是 发布-订阅模式 + 状态机 + 事件循环

1. 基础结构

一个 Promise 对象要有:

  • state:存储当前状态(pending / fulfilled / rejected)。
  • value / reason:存储成功的值或失败的原因。
  • handlers:存放 then 注册的回调函数。

2. 构造函数

ini 复制代码
class MyPromise {
  constructor(executor) {
    this.state = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onFulfilledCallbacks.forEach(fn => fn());
      }
    };

    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };

    try {
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

3. then 方法

  • 返回一个新的 Promise(支持链式调用)。
  • 根据状态执行不同的回调。
  • 若回调返回的是 Promise,需要递归解析(即 Promise 解决过程)。
ini 复制代码
  then(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
    onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e };

    const promise2 = new MyPromise((resolve, reject) => {
      if (this.state === 'fulfilled') {
        queueMicrotask(() => { // 保证异步
          try {
            const x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      }

      if (this.state === 'rejected') {
        queueMicrotask(() => {
          try {
            const x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      }

      if (this.state === 'pending') {
        this.onFulfilledCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              const x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
        });

        this.onRejectedCallbacks.push(() => {
          queueMicrotask(() => {
            try {
              const x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
        });
      }
    });

    return promise2;
  }
}

4. resolvePromise 函数(核心)

处理 then 回调返回值的逻辑:

  • 如果返回的是 普通值 ,直接 resolve
  • 如果返回的是 Promise,递归解析其状态。
  • 避免 循环引用
ini 复制代码
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('Chaining cycle detected'));
  }

  if (x && (typeof x === 'object' || typeof x === 'function')) {
    let called = false;
    try {
      let then = x.then;
      if (typeof then === 'function') {
        then.call(x, y => {
          if (called) return;
          called = true;
          resolvePromise(promise2, y, resolve, reject);
        }, e => {
          if (called) return;
          called = true;
          reject(e);
        });
      } else {
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    resolve(x);
  }
}

四、总结

  • 状态pending → fulfilledpending → rejected,不可逆。

  • 方法

    • 实例方法:thencatchfinally
    • 静态方法:resolverejectallallSettledraceany
  • 原理

    • 通过状态机保证不可逆。
    • 使用回调队列保存 then 回调。
    • 返回新的 Promise 实现链式调用。
    • resolvePromise 负责递归解析,确保符合 Promise/A+ 规范

相关推荐
Ashley的成长之路3 分钟前
NativeScript-Vue 开发指南:直接使用 Vue构建原生移动应用
前端·javascript·vue.js
软件技术NINI1 小时前
MATLAB疑难诊疗:从调试到优化的全攻略
javascript·css·python·html
知识分享小能手2 小时前
uni-app 入门学习教程,从入门到精通,uni-app组件 —— 知识点详解与实战案例(4)
前端·javascript·学习·微信小程序·小程序·前端框架·uni-app
苏打水com2 小时前
从 HTML/CSS/JS 到 React:前端进阶的平滑过渡指南
前端·javascript·html
一枚前端小能手2 小时前
🔐 单点登录还在手动跳转?这几个SSO实现技巧让你的用户体验飞起来
前端·javascript
tianchang2 小时前
深入理解 JavaScript 异步机制:从语言语义到事件循环的全景图
前端·javascript
JNU freshman3 小时前
vue 技巧与易错
前端·javascript·vue.js
Asort3 小时前
JavaScript设计模式(十六)——迭代器模式:优雅遍历数据的艺术
前端·javascript·设计模式
我是日安3 小时前
从零到一打造 Vue3 响应式系统 Day 28 - shallowRef、shallowReactive
前端·javascript·vue.js
开源之眼3 小时前
深入理解 JavaScript 报错:TypeError: undefined is not a function
前端·javascript