You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript实现简易Promise并解决catch错误处理及链式调用问题

自定义Promise错误处理修复方案

现有代码核心问题

  • 缺少Promise状态管理:未定义pending/fulfilled/rejected三种状态,状态变更后没有锁死,导致reject执行后仍会触发resolve逻辑,then回调不会被中断
  • 链式调用返回值错误:then/catch方法直接返回当前实例this,不符合原生Promise每次调用then/catch返回新Promise实例的规范,导致错误无法沿链式调用冒泡
  • 未存储Promise的终值/拒因:异步场景下如果resolve/reject执行时回调还未注册,会丢失结果,也无法判断当前Promise的最终状态

轻量实现调整代码

直接修改Promise.mjs的代码如下:

export default class _Promise {
  // 定义三个状态常量
  static PENDING = 'pending';
  static FULFILLED = 'fulfilled';
  static REJECTED = 'rejected';

  constructor(executor) {
    // 初始化状态、终值、拒因、回调队列
    this.status = _Promise.PENDING;
    this.value = null;
    this.reason = null;
    this.fulfilledCallbacks = [];
    this.rejectedCallbacks = [];

    if (executor && executor instanceof Function) {
      try {
        executor(this.resolve.bind(this), this.reject.bind(this));
      } catch (error) {
        this.reject(error);
      }
    }
  }

  resolve(value) {
    // 只有pending状态才能变更状态
    if (this.status !== _Promise.PENDING) return;
    this.status = _Promise.FULFILLED;
    this.value = value;
    // 执行所有注册的成功回调
    this.fulfilledCallbacks.forEach(cb => cb(value));
  }

  reject(reason) {
    if (this.status !== _Promise.PENDING) return;
    this.status = _Promise.REJECTED;
    this.reason = reason;
    // 执行所有注册的失败回调
    this.rejectedCallbacks.forEach(cb => cb(reason));
  }

  then(onFulfilled, onRejected) {
    // 处理可选参数,默认透传值/错误
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };

    // 每次then返回新的Promise实例,实现链式调用
    return new _Promise((resolve, reject) => {
      // 包装回调,处理返回值的Promise穿透
      const handleFulfilled = () => {
        try {
          const result = onFulfilled(this.value);
          // 如果回调返回的是Promise,等待其状态变更
          result instanceof _Promise ? result.then(resolve, reject) : resolve(result);
        } catch (err) {
          reject(err);
        }
      };

      const handleRejected = () => {
        try {
          const result = onRejected(this.reason);
          result instanceof _Promise ? result.then(resolve, reject) : resolve(result);
        } catch (err) {
          reject(err);
        }
      };

      // 根据当前状态处理回调
      if (this.status === _Promise.PENDING) {
        this.fulfilledCallbacks.push(handleFulfilled);
        this.rejectedCallbacks.push(handleRejected);
      } else if (this.status === _Promise.FULFILLED) {
        setTimeout(handleFulfilled, 0); // 模拟异步执行
      } else if (this.status === _Promise.REJECTED) {
        setTimeout(handleRejected, 0);
      }
    })
  }

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

调整后效果验证

  • 传入非法参数触发reject时,会直接跳过所有后续的成功回调,错误沿链式调用冒泡到最近的catch方法,不会抛出未处理异常
  • 嵌套then中抛出的错误会向外层冒泡,外层catch可以正常捕获
  • 异步执行逻辑和链式调用返回值符合预期,原有正常流程的执行结果不受影响

内容的提问来源于stack exchange,提问作者cj-2307

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 16:36:03