ES6-22【Promise源码重写】

一、Promise源码重写

  1. 基本功能

    class MyPromise { // new的时候传入executor函数
        constructor(executor) {
            this.state = 'pending'; // 提供状态、成功返回值与失败返回值
            this.value = undefined;
            this.reason = undefined;
    
            let resovle = (value) => { // 定义resolve函数
                this.state = 'fullFilled';
                this.value = value;
            }
    
            let reject = (reason) => { // 定义reject函数
                this.state = 'reject';
                this.reason = reason;
            }
    
            executor(resovle, reject); // 提供resolve和reject两个函数
        }
    
        then(onFullFilled, onRejected) { // 定义then方法,接收成功与失败的回调函数
            if (this.state === 'fullFilled') { // 如果状态为成功,则返回成功的返回值,通过形参传给回调函数
                onFullFilled(this.value);
            }
            if (this.state === 'rejected') { // 如果状态为失败,则返回失败的返回值,通过形参传给回调函数
                onRejected(this.reason);
            }
        }
    }
    
    const p1 = new MyPromise((resolve, reject) => {
        resolve(1);
    });
    p1.then((res) => {
        console.log(res);
    }, (err) => {
        console.log(err);
    });
    // 输出1
    
  2. 处理异步任务、绑定多个回调

    executor执行的时候,resolve并没有执行,1秒钟后resolve才执行

    所以说在new MyPromise的时候,MyPromise的状态还是pennding,此时就可以认定是在处理异步任务

    class MyPromise {
        constructor(executor) {
            this.state = 'pending';
            this.value = undefined;
            this.reason = undefined;
            this.onFullFilledCallbacks = []; // 当多次绑定回调,则将其存入对应的成功/失败数组中遍历执行
            this.onRejectedCallbacks = [];
    
            let resovle = (value) => {
                this.state = 'fullFilled';
                this.value = value;
                this.onFullFilledCallbacks.forEach(fn => fn()); // 这里可以传参fn(this.value),但是并不好,应该在then中统一处理参数
            }
    
            let reject = (reason) => {
                this.state = 'reject';
                this.reason = reason;
                this.onRejectedCallbacks.forEach(fn => fn()); // fn(this.reason)
            }
    
            executor(resovle, reject);
        }
    
        then(onFullFilled, onRejected) {
            // 同步情况
            if (this.state === 'fullFilled') {
                onFullFilled(this.value);
            }
            if (this.state === 'rejected') {
                onRejected(this.reason);
            }
            // 异步情况
            if (this.state === 'pending') {
                //             用函数包装一次,有点像代理模式
                this.onFullFilledCallbacks.push(() => {
                    onFullFilled(this.value);
                });
                this.onRejectedCallbacks.push(() => {
                    onRejected(this.reason);
                });
            }
        }
    }
    
    const p1 = new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(1); // executor执行的时候,resolve并没有执行,1秒钟后resolve才执行 
        }, 1000)
    });
    p1.then((res) => {
        console.log(res);
    }, (err) => {
        console.log(err);
    });
    p1.then((res) => {
        console.log(res);
    }, (err) => {
        console.log(err);
    });
    // 输出1 1
    
  3. 链式调用、问题检测工具

    1. 链式调用

      链式操作不能返回this,因为this是上一次的promise,而我们需要返回的是一个全新的promise

      const isFunction = (value) => typeof value === 'function';
      class MyPromise {
          constructor(executor) {
              this.state = 'pending'; // 初始状态:fulfilled,rejected
              this.value = undefined; // 成功的返回值
              this.reason = undefined; // 失败的返回值
              this.onFullFilledCallbacks = [];
              this.onRejectedCallbacks = [];
      
              let resovle = (value) => {
                  this.state = 'fullFilled';
                  this.value = value;
                  this.onFullFilledCallbacks.forEach(fn => fn());
              }
      
              let reject = (reason) => {
                  this.state = 'rejected';
                  this.reason = reason;
                  this.onRejectedCallbacks.forEach(fn => fn());
              }
      
              try {
                  executor(resovle, reject);
              } catch (err) {
                  reject(err);
              }
          }
      
          then(onFullFilled, onRejected) {
              onFullFilled = isFunction(onFullFilled) ? onFullFilled : data => data;
              onRejected = isFunction(onRejected) ? onRejected : err => {
                      throw err;
                  }
                  // 每一次调用then, 都会有一个p2
              const p2 = new MyPromise((resolve, reject) => { // 每当new MyPromise的时候,里面的代码是同步执行的
                  let x;
                  // 同步情况
                  if (this.state === 'fullFilled') {
                      setTimeout(() => {
                          try {
                              x = onFullFilled(this.value);
                              // resolve(x);
                              // 判断返回值是否为promise,然后作相应的处理
                              resolvePromise(p2, x, resolve, reject);
                          } catch (err) {
                              reject(err);
                          }
                      }, 0);
                  }
                  if (this.state === 'rejected') {
                      setTimeout(() => {
                          try {
                              x = onRejected(this.reason);
                              resolvePromise(p2, x, resolve, reject);
                          } catch (err) {
                              reject(err);
                          }
                      }, 0);
                  }
                  // 异步情况
                  if (this.state === 'pending') {
                      this.onFullFilledCallbacks.push(() => {
                          setTimeout(() => {
                              try {
                                  x = onFullFilled(this.value);
                                  resolvePromise(p2, x, resolve, reject);
                              } catch (err) {
                                  reject(err);
                              }
                          }, 0);
                      });
                      this.onRejectedCallbacks.push(() => {
                          setTimeout(() => {
                              try {
                                  x = onRejected(this.reason);
                                  resolvePromise(p2, x, resolve, reject);
                              } catch (err) {
                                  reject(err);
                              }
                          }, 0);
                      });
                  }
              })
      
              return p2; // 返回全新的promise
          }
      }
      
      function resolvePromise(p2, x, resolve, reject) {
          let called;
          if (p2 === x) {
              return reject(new TypeError('typeErr'));
          }
      
          if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
              try {
                  let then = x.then;
                  if (typeof then === 'function') {
                      then.call(x, y => {
                          if (called) return;
                          called = true;
                          // console.log(y);
                          // resolve(y);
                          resolvePromise(p2, y, resolve, reject);
                      }, r => {
                          if (called) return;
                          called = true;
                          // console.log(r)
                          reject(r);
                      })
                  } else {
                      if (called) return;
                      called = true;
                      resolve(x);
                  }
              } catch (err) {
                  if (called) return;
                  called = true;
                  reject(err);
              }
          } else {
              resolve(x);
          }
      }
      
      const p1 = new MyPromise((resolve, reject) => {
          // setTimeout(() => {
          resolve(1);
          // reject(1);
          // }, 1000)
      });
      
      const p2 = p1.then((res) => {
          // console.log(res);
          // 这里希望能够链式操作、返回一个promise
          return new MyPromise((resolve, reject) => {
              resolve(new MyPromise((resolve, reject) => {
                  resolve(new MyPromise((resolve, reject) => {
                      resolve(new MyPromise((resolve, reject) => {
                          resolve(1000);
                      }));
                  }));
              }));
          })
      }, (err) => {
          console.log(err);
          // return err + 2;
      });
      
      p2.then((res) => {
          // 希望res能够拿到上一次回调的结果
          console.log(res, 'success');
      }, (err) => {
          console.log(err);
      });
      
      MyPromise.defer = MyPromise.deferred = function() {
          let dfd = {};
          dfd.promise = new MyPromise((resolve, reject) => {
              dfd.resolve = resolve;
              dfd.reject = reject;
          });
          return dfd;
      };
      // 安装promises-aplus-tests工具测试
      
      module.exports = MyPromise;
      
    2. 问题检测

      安装promises-aplus-tests:

      npm i promises-aplus-tests -g
      

      终端输入如下命令进行检测:

      promises-aplus-tests index.js
      

      输出这样就说明代码没有问题在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值