手写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 小时前
Nodejs也能写Agent - 16.LangGraph篇 - 条件分支与循环
前端·后端·langchain·node.js
To_OC3 小时前
从 “卡死半天” 到 “打字机效果”:大模型流式输出前端实现全记录
前端·javascript·llm
SoaringHeart3 小时前
Flutter最佳实践:键盘辅助视图输入框天添加图片附件
前端·flutter
kyriewen3 小时前
我看完这篇安全论文——AI推荐的npm包,92%是编出来的
前端·javascript·ai编程
小心我捶你啊5 小时前
数据采集和Web解锁不是一回事,从用途到规则区分
前端·爬虫·网络协议
hunterandroid5 小时前
[鸿蒙从零到一] ArkUI 基础组件实战:Text、Image、Button 与 TextInput
前端
fsssb5 小时前
Chromium 源码学习笔记(五):一次点击,在进入 JS 之前先经历了什么?
前端
hunterandroid5 小时前
WorkManager 可靠性实战:唯一任务、重试与幂等设计
android·前端
鹿目5 小时前
使用 Vant CLI 搭建 UI 组件库:从 H5 到小程序跨平台
前端·javascript