手写Promise

  1. 搭建基础结构

    • 新建两个文件,index.html以及promise.js
    • 在index.html中引入promise文件
    • 分别在两个文件中搭建基础结构
    javascript 复制代码
    // index.html
    const p = new Promise((resolve, reject) => {
      resolve("success");
    });
    
    p.then(
      (res) => {
        console.log(res);
      },
      (err) => {
        console.log(err);
      },
    );
    javascript 复制代码
    // promise.js
    
    // 声明构造函数
    function Promise(executor) {}
    
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {};
  2. 补充executor内容

    javascript 复制代码
    // 声明构造函数
    function Promise(executor) {
      // resolve 函数
      function resolve(data) {}
    
      // reject 函数
      function reject(data) {}
    
      // 同步调用执行器函数,因为Promise本身是同步的,所以会立即执行
      executor(resolve, reject);
    }
    
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {};
  3. 补充resolve和reject函数内容

    这两个函数中的this指向为window,所以需要提前保存一下this

    javascript 复制代码
    // 声明构造函数
    function Promise(executor) {
      // 添加属性
      this.PromiseState = "pending"; // 状态(默认未完成)
      this.PromiseResult = null; // 结果值(默认为空)
    
      // 保存实例对象的this值
      const _this = this;
    
      // resolve 函数
      function resolve(data) {
        // 1. 修改对象的状态(PromiseState)
        _this.PromiseState = "fulfilled";
    
        // 2. 设置对象结果值(PromiseResult)
        _this.PromiseResult = data;
      }
    
      // reject 函数
      function reject(data) {
        // 1. 修改对象的状态(PromiseState)
        _this.PromiseState = "rejected";
    
        // 2. 设置对象结果值(PromiseResult)
        _this.PromiseResult = data;
      }
    
      // 同步调用执行器函数,因为Promise本身是同步的,所以会立即执行
      executor(resolve, reject);
    }
    
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {};
  4. 补充throw err的处理内容

    javascript 复制代码
    // index.html
    const p = new Promise((resolve, reject) => {
      throw "error";
    });
    javascript 复制代码
    // promise.js
    
    // 声明构造函数
    function Promise(executor) {
      try {
        // 同步调用执行器函数,因为Promise本身是同步的,所以会立即执行
        executor(resolve, reject);
      } catch (error) {
        // 修改对象的状态为失败
        reject(error);
      }
    }
    
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {};
  5. 补充只改变一次状态的内容

    javascript 复制代码
    // 声明构造函数
    function Promise(executor) {
      // resolve 函数
      function resolve(data) {
        // 判断状态,确保只能修改一次
        if (_this.PromiseState !== "pending") return;
    	
        // 1. 修改对象的状态(PromiseState)
        _this.PromiseState = "fulfilled";
    
        // 2. 设置对象结果值(PromiseResult)
        _this.PromiseResult = data;
      }
    
      // reject 函数
      function reject(data) {
        // 判断状态,确保只能修改一次
        if (_this.PromiseState !== "pending") return;
    
        // 1. 修改对象的状态(PromiseState)
        _this.PromiseState = "rejected";
    
        // 2. 设置对象结果值(PromiseResult)
        _this.PromiseResult = data;
      }
    }
    
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {};
  6. 补充then方法回调执行的内容

    javascript 复制代码
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {
      if (this.PromiseState === "fulfilled") {
        onFulfilled(this.PromiseResult);
      } else {
        onRejected(this.PromiseResult);
      }
    };
  7. 补充异步任务回调处理的内容

    • 因为代码执行是同步的,存在setTimeout以后就成为了异步,导致状态还没有改变就执行到了then方法,又因为then方法里只有状态为fulfilled和rejected的处理函数,所以导致状态为pending时的情况没有被处理。
    • setTimeout是异步的,所以需要等待1000毫秒过后再去执行then方法,因此在pending状态的时候需要将then中的onFulfilled和onRejected方法暂时存储起来,放入构造函数的callback中。
    • 当1000毫秒过后,执行了setTimeout中的resolve方法,触发了构造函数中定义的resolve函数,这时状态已经变化,可以通过判断callback中是否存在对应的处理函数就可以调用对应的回调方法。
    javascript 复制代码
    // index.html
    
    const p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("success");
      }, 1000);
    });
    javascript 复制代码
    // promise.js
    
    // 声明构造函数
    function Promise(executor) {
      // 添加回调函数存储容器
      this.callback = {};
    
      // resolve 函数
      function resolve(data) {
        // 判断状态,确保只能修改一次
        if (_this.PromiseState !== "pending") return;
    
        // 1. 修改对象的状态(PromiseState)
        _this.PromiseState = "fulfilled";
    
        // 2. 设置对象结果值(PromiseResult)
        _this.PromiseResult = data;
    
        // 判断回调函数是否存在,存在则调用
        if (_this.callback.onFulfilled) {
          _this.callback.onFulfilled(data);
        }
      }
    
      // reject 函数
      function reject(data) {
        // 判断状态,确保只能修改一次
        if (_this.PromiseState !== "pending") return;
    
        // 1. 修改对象的状态(PromiseState)
        _this.PromiseState = "rejected";
    
        // 2. 设置对象结果值(PromiseResult)
        _this.PromiseResult = data;
    
        // 判断回调函数是否存在,存在则调用
        if (_this.callback.onRejected) {
          _this.callback.onRejected(data);
        }
      }
    }
    
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {
      if (this.PromiseState === "fulfilled") {
        onFulfilled(this.PromiseResult);
      }
      if (this.PromiseState === "rejected") {
        onRejected(this.PromiseResult);
      }
      // 存储pending状态时的回调函数,不让立即执行
      if (this.PromiseState === "pending") {
        this.callback = {
          onFulfilled,
          onRejected,
        };
      }
    };
  8. 补充多个then回调的内容

    javascript 复制代码
    // index.html
    
    const p = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("success");
        // reject("err");
      }, 1000);
    });
    
    p.then(
      (res) => {
        console.log(res, "---------19");
      },
      (err) => {
        console.log(err, "---------23");
      },
    );
    
    p.then(
      (res) => {
        console.log(res, "---------30");
      },
      (err) => {
        console.log(err, "---------33");
      },
    );
    javascript 复制代码
    // promise.js
    
    // 声明构造函数
    function Promise(executor) {
      // 添加回调函数存储容器
      this.callbacks = [];
    
      // resolve 函数
      function resolve(data) {
        // 判断状态,确保只能修改一次
        if (_this.PromiseState !== "pending") return;
    
        // 1. 修改对象的状态(PromiseState)
        _this.PromiseState = "fulfilled";
    
        // 2. 设置对象结果值(PromiseResult)
        _this.PromiseResult = data;
    
        // 判断回调函数是否存在,存在则调用
        _this.callbacks.forEach((item) => {
          item.onFulfilled(data);
        });
      }
    
      // reject 函数
      function reject(data) {
        // 判断状态,确保只能修改一次
        if (_this.PromiseState !== "pending") return;
    
        // 1. 修改对象的状态(PromiseState)
        _this.PromiseState = "rejected";
    
        // 2. 设置对象结果值(PromiseResult)
        _this.PromiseResult = data;
    
        // 判断回调函数是否存在,存在则调用
        _this.callbacks.forEach((item) => {
          item.onRejected(data);
        });
      }
    }
    
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {
      if (this.PromiseState === "fulfilled") {
        onFulfilled(this.PromiseResult);
      }
      if (this.PromiseState === "rejected") {
        onRejected(this.PromiseResult);
      }
      // 存储pending状态时的回调函数,不让立即执行
      if (this.PromiseState === "pending") {
        this.callbacks.push({
          onFulfilled,
          onRejected,
        });
      }
    };
  9. 补充then方法的返回值-同步

    因为then的返回值类型是Promise,所以只需要在then方法里返回一个Promise对象即可

    返回值的几种情况:

    1)当返回值为非Promise类型,则直接返回成功状态

    2)当返回值为Promise类型,则返回值依赖于回调的返回值

    3)当回调发生错误,则直接返回失败状态

    javascript 复制代码
    // 添加then方法
    Promise.prototype.then = function (onFulfilled, onRejected) {
      // then方法返回的是一个Promise对象,通过return new Promise来创建
      return new Promise((resolve, reject) => {
        if (this.PromiseState === "fulfilled") {
          try {
          	// 通过onFulfilled可以获取到回调函数的返回值
            const result = onFulfilled(this.PromiseResult);
    
            // 根据回调函数的值来判断返回结果
            if (result instanceof Promise) {
              // 是Promise类型则具有then方法
              result.then(
                (v) => {
                  resolve(v);
                },
                (e) => {
                  reject(e);
                },
              );
            } else {
              // 不为Promise类型则直接返回成功
              resolve(result);
            }
          } catch (error) {
            // 处理throw抛出的异常
            reject(error);
          }
        }
    
        if (this.PromiseState === "rejected") {
          try {
            const result = onRejected(this.PromiseResult);
    
            if (result instanceof Promise) {
              result.then(
                (v) => {
                  resolve(v);
                },
                (e) => {
                  reject(e);
                },
              );
            } else {
              resolve(result);
            }
          } catch (error) {
            reject(error);
          }
        }
    
        // 存储pending状态时的回调函数,不让立即执行
        if (this.PromiseState === "pending") {
          this.callbacks.push({
            onFulfilled,
            onRejected,
          });
        }
      });
    };
  10. 补充then方法的返回值-异步

    javascript 复制代码
    Promise.prototype.then = function (onFulfilled, onRejected) {
      const _this = this;
    
      // then方法返回的是一个Promise对象,通过return new Promise来创建
      return new Promise((resolve, reject) => {
        // 存储pending状态时的回调函数,不让立即执行
        if (this.PromiseState === "pending") {
          this.callbacks.push({
          	// 改造成这样能保证异步函数依旧能正常执行,在这个基础上再进行返回值的处理
            // onFulfilled: function () {
            //   onFulfilled(_this.PromiseResult);
            // },
            
          	// 对之前的存储方法进行改造,同样是根据回调函数的返回值进行判断返回的是成功还是失败
            onFulfilled: function () {
              try {
                const result = onFulfilled(_this.PromiseResult);
                if (result instanceof Promise) {
                  result.then(
                    (v) => {
                      resolve(v);
                    },
                    (e) => {
                      reject(e);
                    },
                  );
                } else {
                  resolve(result);
                }
              } catch (error) {
                reject(error);
              }
            },
            onRejected: function () {
              try {
                const result = onRejected(_this.PromiseResult);
                if (result instanceof Promise) {
                  result.then(
                    (v) => {
                      resolve(v);
                    },
                    (e) => {
                      reject(e);
                    },
    	          );
        	    } else {
            	  resolve(result);
                }
    	      } catch (error) {
        	    reject(error);
        	  }
        	},
    	  });
        }
      });
    };
  11. then方法优化

    javascript 复制代码
    Promise.prototype.then = function (onFulfilled, onRejected) {
      const _this = this;
    
      // then方法返回的是一个Promise对象,通过return new Promise来创建
      return new Promise((resolve, reject) => {
        // 封装函数
        function callback(type) {
          try {
            // 通过type(onFulfilled)可以获取到回调函数的返回值
            const result = type(_this.PromiseResult);
    
            // 根据回调函数的值来判断返回结果
            if (result instanceof Promise) {
              // 是Promise类型则具有then方法
              result.then(
                (v) => {
                  resolve(v);
                },
                (e) => {
                  reject(e);
                },
              );
            } else {
              // 不为Promise类型则直接返回成功
              resolve(result);
            }
          } catch (error) {
            // 处理throw抛出的异常
            reject(error);
          }
        }
    
        if (this.PromiseState === "fulfilled") {
          callback(onFulfilled);
        }
    
        if (this.PromiseState === "rejected") {
          callback(onRejected);
        }
    
        // 存储pending状态时的回调函数,不让立即执行
        if (this.PromiseState === "pending") {
          this.callbacks.push({
            // 改造成这样能保证异步函数依旧能正常执行,在这个基础上再进行返回值的处理
            // onFulfilled: function () {
            //   onFulfilled(_this.PromiseResult);
            // },
            onFulfilled: function () {
              callback(onFulfilled);
            },
            onRejected: function () {
              callback(onRejected);
            },
          });
        }
      });
    };
相关推荐
Mike_jia1 小时前
中国版的OpenClaw--OpenOcta(八爪鱼)为运维人打造的 7×24h 数字员工
前端
Ronin3051 小时前
【Qt常用控件】输入类控件
开发语言·qt·常用控件·输入类控件
健康平安的活着1 小时前
java中事务@Transaction的正确使用和触发回滚机制【经典】
java·开发语言
全栈软件开发1 小时前
中小汽修门店汽修单管理系统PHP源码,数字化管理维修订单与客户信息
开发语言·php
Barkamin1 小时前
使用PriorityQueue创建大小堆,解决TOPK问题
java·开发语言
寻寻觅觅☆1 小时前
东华OJ-进阶题-12-时间转换(C++)
开发语言·c++·算法
还是大剑师兰特1 小时前
50个 filter相关的公共函数
开发语言·javascript·ecmascript
biubiubiu07062 小时前
Chrome DevTools在Agent编程工具上的安装
前端·chrome·chrome devtools