Skip to content

Promise

一、三种状态(不可逆)

  • pending(待定):初始状态,操作未完成
  • fulfilled(已兑现):操作成功,通过 resolve()
  • rejected(已拒绝):操作失败,通过 reject()

二、基本用法

1. 创建 Promise

javascript
const p = new Promise((resolve, reject) => {
  // 异步操作:请求、定时器等
  setTimeout(() => {
    const ok = true
    if (ok) {
      resolve('成功数据') // 变为 fulfilled
    } else {
      reject(new Error('失败原因')) // 变为 rejected
    }
  }, 1000)
})

2. then / catch / finally

javascript
p
  .then(value => {
    console.log('成功:', value) // 处理 resolve
    return value + ' 处理后' // 可返回新值/新Promise
  })
  .then(newValue => console.log(newValue))
  .catch(err => {
    console.error('失败:', err) // 处理 reject/异常
  })
  .finally(() => {
    console.log('无论成败都执行') // 清理、收尾
  })

三、常用静态方法

  • Promise.resolve(value):直接返回 fulfilled 状态
  • Promise.reject(reason):直接返回 rejected 状态
  • Promise.all([p1,p2,...])全部成功才成功,返回结果数组;任一失败则整体失败
  • Promise.race([p1,p2,...])谁先敲定(成功/失败)就用谁的结果
  • Promise.allSettled([p1,p2,...]):全部执行完,返回每个结果(含状态)
  • Promise.any([p1,p2,...])任一成功即成功;全失败才失败

四、async/await

javascript
async function fetchData() {
  try {
    const res = await fetch('/api') // 等待 Promise 完成
    const data = await res.json()
    console.log(data)
  } catch (err) {
    console.error(err) // 捕获 reject/异常
  }
}
fetchData()

MyPromise

js
class MyPromise {
  static PENDING = 'pending';
  static FULFILLED = 'fulfilled';
  static REJECTED = 'rejected';

  constructor(executor) {
    this.status = MyPromise.PENDING;
    this.value = undefined;
    this.reason = undefined;
    // 存储多个 then 回调
    this.onFulfilledCbs = [];
    this.onRejectedCbs = [];

    const resolve = (value) => {
      if (this.status === MyPromise.PENDING) {
        this.status = MyPromise.FULFILLED;
        this.value = value;
        // 微任务批量执行回调
        queueMicrotask(() => {
          this.onFulfilledCbs.forEach(cb => cb());
        });
      }
    };

    const reject = (reason) => {
      if (this.status === MyPromise.PENDING) {
        this.status = MyPromise.REJECTED;
        this.reason = reason;
        queueMicrotask(() => {
          this.onRejectedCbs.forEach(cb => cb());
        });
      }
    };

    // 捕获执行器同步异常
    try {
      executor(resolve, reject);
    } catch (err)
      reject(err);
    }
  }

  // 核心:Promise/A+ 规范 resolvePromise 解析器
  static resolvePromise(x, promise2, resolve, reject) {
    // 1. 循环引用检测:返回自身直接报错
    if (x === promise2) {
      return reject(new TypeError('Chaining cycle detected for promise'));
    }

    // 标记是否已执行,防止 then 内多次调用 resolve/reject
    let called = false;

    // 2. x 是对象/函数:可能是 thenable
    if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
      try {
        const then = x.then;
        // 是标准 thenable
        if (typeof then === 'function') {
          then.call(
            x,
            y => {
              if (called) return;
              called = true;
              // 递归解析 y
              MyPromise.resolvePromise(y, promise2, resolve, reject);
            },
            r => {
              if (called) return;
              called = true;
              reject(r);
            }
          );
        } else {
          // 普通对象无 then,直接 resolve
          resolve(x);
        }
      } catch (e) {
        if (called) return;
        called = true;
        reject(e);
      }
    } else {
      // 3. 普通基本类型值,直接决议
      resolve(x);
    }
  }

  then(onFulfilled, onRejected) {
    // 规范:回调穿透兜底
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; };

    // then 必须返回新 Promise2
    const promise2 = new MyPromise((resolve, reject) => {
      // 成功处理逻辑
      const handleFulfilled = () => {
        queueMicrotask(() => {
          try {
            const x = onFulfilled(this.value);
            MyPromise.resolvePromise(x, promise2, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      };

      // 失败处理逻辑
      const handleRejected = () => {
        queueMicrotask(() => {
          try {
            const x = onRejected(this.reason);
            MyPromise.resolvePromise(x, promise2, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      };

      // 状态分支处理
      switch (this.status) {
        case MyPromise.FULFILLED:
          handleFulfilled();
          break;
        case MyPromise.REJECTED:
          handleRejected();
          break;
        case MyPromise.PENDING:
          this.onFulfilledCbs.push(handleFulfilled);
          this.onRejectedCbs.push(handleRejected);
          break;
      }
    });

    return promise2;
  }

  catch(onRejected) {
    return this.then(null, onRejected);
  }

  finally(callback) {
    return this.then(
      val => MyPromise.resolve(callback()).then(() => val),
      err => MyPromise.resolve(callback()).then(() => { throw err; })
    );
  }

  static resolve(value) {
    if (value instanceof MyPromise) return value;
    return new MyPromise(res => res(value));
  }

  static reject(reason) {
    return new MyPromise((_, rej) => rej(reason));
  }
}