手写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);
// });
相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学3 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端