手撸自己的Promise,Promise手写代码

55 阅读3分钟

手撸自己的Promise,Promise手写代码

在我们开始前,我们先对Promise进行一个了解,首先Promise是一个类,在执行这个类的时候需要传递一个执行器进去,并立即执行,执行器接受两个参数:resolve和reject两个方法;再有就是Promise有三种状态:等待pending、成功fullfilled和失败rejected;当然我们在使用Promise时,它还拥有then和catch方法;最后也需要实现Promise.resolve、Promise.resolve、Promise.all和Promise.race的实现。

  1. 首先我们创建一个MyPromise.html文件,将所用到的情况都写下来,便于我们写Promise时避免遗漏和方便测试和编写

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>MyPromise</title>
      </head>
    ​
      <body>
        <h1>MyPromise</h1>
        <script src="./MyPromise.js"></script>
        <script>
          const p1 = new MyPromise((resolve, reject) => {
            // resolve(100);
            setTimeout(() => {
              resolve(100);
            }, 1000);
          });
          p1.then((data1) => {
            return data1 + 1;
          })
            .then((data2) => {
              return data2 + 2;
            })
            .catch((err) => {
              console.log(err);
            });
    ​
          const p2 = MyPromise.resolve(200);
          const p3 = MyPromise.reject(300);
          const p4 = MyPromise.all([p1, p2]);
          const p5 = MyPromise.race([p2, p3]);
          console.log(p5);
        </script>
      </body>
    </html>
    
  1. 我们创建MyPromise.js的文件并创建类MyPromise

    /**
     * @description MyPromise
     * @author gsx
     */
    class MyPromise {
     
    };
    
  1. 根据对Promise的描述我们定义好一些属性和方法

    /**
     * @description MyPromise
     * @author gsx
     */
    class MyPromise {
      state = "pending"; //状态 pending fulfilled rejected
      value = undefined; // 成功后的值
      reason = undefined; // 失败后的原因
    ​
      resolveCallbacks = []; // padding状态下 成功回调
      rejectCallbacks = []; // padding状态下 失败回调
    ​
      constructor(fn) {
        const resolveHandler = (value) => {
          if (this.state === "pending") {
            this.state = "fulfilled";
            this.value = value;
            this.resolveCallbacks.forEach((fn) => fn(this.value));
          }
        };
        const rejectHandler = (reason) => {
          if (this.state === "pending") {
            this.state = "rejected";
            this.reason = reason;
            this.rejectCallbacks.forEach((fn) => fn(this.reason));
          }
        };
        try {
          fn(resolveHandler, rejectHandler);
        } catch (error) {
          rejectHandler(error);
        }
      }
      then(fn1, fn2) {
        // 当pending状态下,fn1 fn2 会被储存到callbacks中
      }
      // 就是then的一个语法糖
      catch(fn) {
        return this.then(null, fn);
      }
    }
    
  1. 接下来我们来完成then

    /**
     * @description MyPromise
     * @author gsx
     */
    class MyPromise {
      ...
      then(fn1, fn2) {
        // 当pending状态下,fn1 fn2 会被储存到callbacks中
        fn1 = typeof fn1 === "function" ? fn1 : (value) => value;
        fn2 = typeof fn2 === "function" ? fn2 : (error) => error;
        if (this.state === "pending") {
          return new MyPromise((resolve, reject) => {
            this.resolveCallbacks.push(() => {
              try {
                const result = fn1(this.value);
                resolve(result);
              } catch (error) {
                reject(error);
              }
            });
            this.rejectCallbacks.push(() => {
              try {
                const result = fn1(this.reason);
                reject(result);
              } catch (error) {
                reject(error);
              }
            });
          });
        }
        if (this.state === "fulfilled") {
          return new MyPromise((resolve, reject) => {
            try {
              const result = fn1(this.value);
              resolve(result);
            } catch (error) {
              reject(error);
            }
          });
        }
        if (this.state === "rejected") {
          return new MyPromise((__, reject) => {
            try {
              const result = fn2(this.reason);
              reject(result);
            } catch (error) {
              reject(error);
            }
          });
        }
      }
      // 就是then的一个语法糖
      catch(fn) {
        return this.then(null, fn);
      }
    }
    ​
    
  1. 完成resolve、reject、all、race

    /**
     * @description MyPromise
     * @author gsx
     */
    class MyPromise {
     ...
    }
    MyPromise.resolve = function (value) {
      return new MyPromise((resolve) => {
        resolve(value);
      });
    };
    ​
    MyPromise.reject = function (reason) {
      return new MyPromise((__, reject) => {
        reject(reason);
      });
    };
    ​
    MyPromise.all = function (promiseList = []) {
      return new MyPromise((resolve, reject) => {
        const result = []; // 存储结果
        const length = promiseList.length;
        let resolvedCount = 0;
        promiseList.forEach((promise, index) => {
          promise
            .then((value) => {
              result[index] = value;
              resolvedCount++;
              if (resolvedCount === length) {
                resolve(result);
              }
            })
            .catch((error) => {
              reject(error);
            });
        });
      });
    };
    ​
    MyPromise.race = function (promiseList = []) {
      return new MyPromise((resolve, reject) => {
        let resolved = false;
        promiseList.forEach((promise) => {
          promise
            .then((value) => {
              if (!resolved) {
                resolved = true;
                resolve(value);
              }
            })
            .catch((error) => {
              reject(error);
            });
        });
      });
    };
    ​
    

完整代码

/**
 * @description MyPromise
 * @author gsx
 */
class MyPromise {
  state = "pending"; //状态 pending fulfilled rejected
  value = undefined; // 成功后的值
  reason = undefined; // 失败后的原因
​
  resolveCallbacks = []; // padding状态下 成功回调
  rejectCallbacks = []; // padding状态下 失败回调
​
  constructor(fn) {
    const resolveHandler = (value) => {
      if (this.state === "pending") {
        this.state = "fulfilled";
        this.value = value;
        this.resolveCallbacks.forEach((fn) => fn(this.value));
      }
    };
    const rejectHandler = (reason) => {
      if (this.state === "pending") {
        this.state = "rejected";
        this.reason = reason;
        this.rejectCallbacks.forEach((fn) => fn(this.reason));
      }
    };
    try {
      fn(resolveHandler, rejectHandler);
    } catch (error) {
      rejectHandler(error);
    }
  }
  then(fn1, fn2) {
    // 当pending状态下,fn1 fn2 会被储存到callbacks中
    fn1 = typeof fn1 === "function" ? fn1 : (value) => value;
    fn2 = typeof fn2 === "function" ? fn2 : (error) => error;
    if (this.state === "pending") {
      return new MyPromise((resolve, reject) => {
        this.resolveCallbacks.push(() => {
          try {
            const result = fn1(this.value);
            resolve(result);
          } catch (error) {
            reject(error);
          }
        });
        this.rejectCallbacks.push(() => {
          try {
            const result = fn1(this.reason);
            reject(result);
          } catch (error) {
            reject(error);
          }
        });
      });
    }
    if (this.state === "fulfilled") {
      return new MyPromise((resolve, reject) => {
        try {
          const result = fn1(this.value);
          resolve(result);
        } catch (error) {
          reject(error);
        }
      });
    }
    if (this.state === "rejected") {
      return new MyPromise((__, reject) => {
        try {
          const result = fn2(this.reason);
          reject(result);
        } catch (error) {
          reject(error);
        }
      });
    }
  }
  // 就是then的一个语法糖
  catch(fn) {
    return this.then(null, fn);
  }
}
MyPromise.resolve = function (value) {
  return new MyPromise((resolve) => {
    resolve(value);
  });
};
​
MyPromise.reject = function (reason) {
  return new MyPromise((__, reject) => {
    reject(reason);
  });
};
​
MyPromise.all = function (promiseList = []) {
  return new MyPromise((resolve, reject) => {
    const result = []; // 存储结果
    const length = promiseList.length;
    let resolvedCount = 0;
    promiseList.forEach((promise, index) => {
      promise
        .then((value) => {
          result[index] = value;
          resolvedCount++;
          if (resolvedCount === length) {
            resolve(result);
          }
        })
        .catch((error) => {
          reject(error);
        });
    });
  });
};
​
MyPromise.race = function (promiseList = []) {
  return new MyPromise((resolve, reject) => {
    let resolved = false;
    promiseList.forEach((promise) => {
      promise
        .then((value) => {
          if (!resolved) {
            resolved = true;
            resolve(value);
          }
        })
        .catch((error) => {
          reject(error);
        });
    });
  });
};
​

快试试吧!