手写promise

promise有一个then方法

  • 1、构造函数
  • 2、then方法
js 复制代码
promise A+规范,有then方法就可以;所以难点是then方法
new Promise((resolve, reject) => {})
观察Promise的用法,构造函数会传入一个函数,执行器executor
resolve和reject两个函数用来改变状态,pending -》 fullfiled 或 pending-〉rejected

1 构造函数

kotlin 复制代码
// 用常量定义字符串,利于维护
const PENDING = 'pending';
const FULLFIED = 'fullfied';
const REJECTED = 'rejected';
class MyPromise {
  #status = PENDING; // 变量前加#,表示私有属性
  #result = undefined;
  #handlers = [];
  constructor(executor) {
    const resolve = (data) => {
      this.#changeState(FULLFIED, data);
    };

    const reject = (reason) => {
      this.#changeState(REJECTED, reason);
    };

    // try catch 只能捕获同步错误
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }

  #changeState(status, data) {
    if (this.#status !== PENDING) {
      return;
    }
    this.#status = status;
    this.#result = data;
    console.log(this.#status, this.#result);
    #run();
  }
 }

2 接下来考虑then

graph TD then --> handler then --> #run #changeState --> #run #run --> handler
arduino 复制代码
// 传入的回调什么时候运行:将回调收集起来,用户可能会调用多次then,所以使用数组收集
// then返回的promise
// 挂起的状态,有异步代码情况,所以需要状态改变时执行回调函数
// 将回调函数都收集起来

// 传入的回调不是函数,穿透
// 目前状态是成功,传入的回调不是函数
// 目前状态是失败,传入的回调不是函数

// 运行回调函数,返回回调函数运行结果【&执行回调】
js 复制代码
#runOne(callback, resolve, reject) {
    if (typeof callback !== 'function') {
      const settled = this.#status === FULLFIED ? resolve : reject;
      settled(this.#result);
      return;
    }

    try {
      const data = callback(this.#result);
      resolve(data);【&执行回调】
    } catch (err) {
      reject(err);
    }
}

// 在changeState状态改变函数中也要调用run方法
#run() {
    if (this.#status === PENDING) return;
    while (this.#handlers.length) {
      const { onFullfilled, onRejected, resolve, reject } =
        this.#handlers.shift();

      if (this.#status === FULLFIED) {
        this.#runOne(onFullfilled, resolve, reject);
      } else {
        this.#runOne(onRejected, resolve, reject);
      }
      // 提取函数runOne
      // if (this.#status === FULLFIED) {
      //   if (typeof onFullfilled === 'function') {
      //     try {
      //       const data = onFullfilled(this.#result);
      //       resolve(data);
      //     } catch (err) {
      //       reject(err);
      //     }
      //   } else {
      //     resolve(this.#result);
      //   }
      // } else {
      //   if (typeof onRejected === 'function') {
      //     try {
      //       const data = onRejected(this.#result);
      //       resolve(data);
      //     } catch (err) {
      //       reject(err);
      //     }
      //     onRejected(this.#result);
      //   } else {
      //     // 目前状态时成功,传入的回调不是函数
      //     // 目前状态时失败,传入的回调不是函数
      //     // 穿透,resolve或者reject
      //     // 穿透
      //     reject(this.#result);
      //   }
      // }
    }
  }
  // 传入的回调什么时候运行:将回调收集起来,用户可能会调用多次then,所以使用数组收集
  // then返回的promise
  then(onFullfilled, onRejected) {
    return new Promise((resolve, reject) => {
      // 挂起的状态,有异步代码情况,所以需要状态改变时执行回调函数
      // 将回调函数都收集起来
      this.#handlers.push({
        onFullfilled,
        onRejected,
        resolve,
        reject,
      });

      this.#run();
    });
  }
js 复制代码
const p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject(234);
  }, 1000);

  // throw 123;
});
console.log(p);

p.then(
  (res) => {
    console.log('成功1', res);
  },
  (err) => {
    console.log('失败1', err);
  }
);
p.then(
  // (res) => {
  //   console.log('成功2', res);
  // },
  null,
  (err) => {
    console.log('失败2', err);
  }
);
p.then(
  (res) => {
    console.log('成功3', res);
  },
  (err) => {
    console.log('失败3', err);
    return 222;
  }
).then((res) => {
  console.log(res);
});

// 原生promise也无法捕获异步错误
// const p1 = new Promise((resolve, reject) => {
//   setTimeout(() => {
//     throw 123;
//   }, 0);
// });
相关推荐
兄弟加油,别颓废了。1 分钟前
系统全功能详细操作手册,从启动到测试
前端·chrome
ZC跨境爬虫18 分钟前
跟着 MDN 学 HTML day_32:(AbstractRange 抽象接口与 DOM 范围操作)
前端·javascript·ui·html·音视频
十子木22 分钟前
设置把所有终端移动到最前端的快捷键
前端
陈老老老板24 分钟前
Bright Data Web Scraping 实战:用 MCP + Dify 构建 eBay 商品详情采集 AI 工作流(2026)
前端·人工智能
一渊之隔33 分钟前
uniapp蓝牙搜索连接展示蓝牙设备包含信号显示
前端·网络·uni-app·bluetooth
Cisyam^39 分钟前
Bright Data Web Scraper 实战:构建 TikTok 与 LinkedIn Web Scraping 自动化 Skill(2026)
运维·前端·自动化
李剑一1 小时前
开箱即用!Vue3+TS 视频组件完整代码,自动提取视频第一帧做封面。妈妈再也不用担心我手动截封面了
前端
盐多碧咸。。1 小时前
echarts折线图矩形选择 框选图表
前端·javascript·echarts
羽沢311 小时前
Canvas学习一
前端·css·学习·canvas
KaMeidebaby1 小时前
卡梅德生物技术快报|锦葵科植物遗传转化工程化优化:棉花胚尖农杆菌转化体系参数固化与效率提升
前端