美文网首页
手写promise

手写promise

作者: 皮神雷卡丘 | 来源:发表于2019-10-14 11:02 被阅读0次

    1)构造函数中立即执行函数
    2)resolve和reject,Promise.resolve()这样的方法是存在于构造函数的方法,在es6中用static关键字
    3)状态机
    4)实现then(链式调用),then应该返回同自己类型的promise,并且是全新的对象
    5)实现resolve的异步调用,用了asyncQueue一个队列,将then传入的回调函数推入队列,没有调用resolve之前一定为pending状态,此时调用then就返回自身,得以保存队列完整,调用resolve之后再for循环 同步阻塞调用执行,返回一个全新的promise进行迭代
    (resolvePromise)是Promise处理的一个标准

    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    
    export default class MyPromsie<T> {
    
      private state: string = '';
      private val: string = '';
      private reason: string = '';
      // 实现异步调用队列
      private asyncQueue: IPromiseCBS[] = [];
    
      constructor(executor: <T = any>(resolve?: (value?: any) => void, reject?: (reason?: any) => void) => void) {
        // 初始化状态机
        this.state = PENDING;
    
        try {
          executor((val: any) => { this.resolve(val) }, (reason: any) => { this.reject(reason) });
        } catch (reason) {
          this.reject(reason);
        }
      }
      // then function
      public then(onFulfilled?: (val: any) => any, onRejected?: (reason: any) => any): MyPromsie<T> {
        let promise: MyPromsie<T>;
        // 异步情况 还未通过resolve改变pending状态
        if (this.state === PENDING) {
          // 箭头函数 阻止this 丢失
          const ele = { onFulfilled, onRejected } as IPromiseCBS;
          this.asyncQueue.push(ele);
          return this;
        }
        promise = new MyPromsie((resolve, reject) => {
          if (this.state === FULFILLED) {
            // onFuifilled 的参数为 fulfilled 状态时的val值,并返回一个新的值作为新的promise resolve的入参
            try {
              const x = onFulfilled(this.val)
              resolve(x);
            } catch (reason) {
              reject(reason);
            }
          }
    
          if (this.state === REJECTED) {
            try {
              const x = onRejected(this.reason)
              // todo resolvePromise()
              resolve(x);
            } catch (reason) {
              reject(reason);
            }
          }
        });
        console.log(promise);
        return promise;
      }
    
      public catch() {
    
      }
    
      public finally() {
    
      }
    
      private resolve(val: any) {
        if (this.state === PENDING) {
          this.state = FULFILLED;
          // 保存调用resolve的值
          this.val = val;
          this.queueExecutor();
        }
      }
    
      private reject(reason: any) {
        if (this.state === PENDING) {
          this.state = REJECTED;
          // 保存调用reject的值
          this.reason = reason;
          this.queueExecutor();
        }
      }
    
      private queueExecutor() {
        // 如果resolve被异步调用 队列必不为空
        if (this.asyncQueue.length > 0) {
          let promise: MyPromsie<any> = this;
          // for 循环为 同步 阻塞调用
          for (let index = 0; index < this.asyncQueue.length; index++) {
            const element = this.asyncQueue[index];
            promise = promise.then(element.onFulfilled, element.onRejected);
          }
        }
      }
      // Promise.resolve()
      static resolve(val: any) {
        console.log(`static resolve val = ${val}`)
      }
      // Promise.reject()
      static reject(reason: any) {
        console.log(`static reject reason = ${reason}`)
      }
    
    }
    
    interface IPromiseCBS {
      onFulfilled?: (val: any) => any;
      onRejected?: (reason: any) => any;
    }
    

    实现Promise.all .race resolve reject,最终为

    const PENDING = 'pending';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    
    export default class MyPromsie<T> {
    
      private state: string = '';
      private val: string = '';
      private reason: string = '';
      // 实现异步调用队列
      private asyncQueue: IPromiseCBS[] = [];
    
      constructor(executor: <T = any>(resolve?: (value?: any) => void, reject?: (reason?: any) => void) => void) {
        // 初始化状态机
        this.state = PENDING;
    
        try {
          executor((val: any) => { this.resolve(val) }, (reason: any) => { this.reject(reason) });
        } catch (reason) {
          this.reject(reason);
        }
      }
      // then function
      public then(onFulfilled?: (val: any) => any, onRejected?: (reason: any) => any): MyPromsie<T> {
        let promise: MyPromsie<T>;
        // 异步情况 还未通过resolve改变pending状态
        if (this.state === PENDING) {
          // 箭头函数 阻止this 丢失
          const ele = { onFulfilled, onRejected } as IPromiseCBS;
          this.asyncQueue.push(ele);
          return this;
        }
        promise = new MyPromsie((resolve, reject) => {
          if (this.state === FULFILLED) {
            // onFuifilled 的参数为 fulfilled 状态时的val值,并返回一个新的值作为新的promise resolve的入参
            try {
              const x = onFulfilled(this.val)
              resolve(x);
            } catch (reason) {
              reject(reason);
            }
          }
    
          if (this.state === REJECTED) {
            try {
              const x = onRejected(this.reason)
              // todo resolvePromise()
              resolve(x);
            } catch (reason) {
              reject(reason);
            }
          }
        });
        // console.log(promise);
        return promise;
      }
      // 实质为 onFuifilled 回调为空
      public catch(onRejected?: (reason: any) => any) {
        this.then(null,onRejected);
      }
      // finally 总是被执行的 无论成功还是 promise被拒绝 先执行.then中 成功或者失败的回调再调用finally的回调函数
      public finally(cbs: Function) {
        cbs();
      }
    
      private resolve(val: any) {
        if (this.state === PENDING) {
          this.state = FULFILLED;
          // 保存调用resolve的值
          this.val = val;
          this.queueExecutor();
        }
      }
    
      private reject(reason: any) {
        if (this.state === PENDING) {
          this.state = REJECTED;
          // 保存调用reject的值
          this.reason = reason;
          this.queueExecutor();
        }
      }
    
      private queueExecutor() {
        // 如果resolve被异步调用 队列必不为空
        if (this.asyncQueue.length > 0) {
          let promise: MyPromsie<any> = this;
          // 这么写 如果onFulfilled onRejected如果有异步函数 依然是有问题的啊  得不到顺序执行
          for (let index = 0; index < this.asyncQueue.length; index++) {
            const element = this.asyncQueue[index];
            promise = promise.then(element.onFulfilled, element.onRejected);
          }
        }
      }
      // Promise.resolve()
      static resolve(val?: any) {
        console.log(`static resolve val = ${val}`)
        return new MyPromsie((resolve, reject) => {
          resolve(val);
        });
      }
      // Promise.reject()
      static reject(reason?: any) {
        console.log(`static reject reason = ${reason}`)
        return new MyPromsie((resolve, reject) => {
          reject(reason);
        });
      }
      // 输入promise数组 哪个promise 先执行完就返回哪个
      static race(pArray: MyPromsie<any>[]) {
        return new MyPromsie((resolve, reject) => {
          for (let i = 0; i < pArray.length; i++) {
            pArray[i].then(resolve, reject)
          };
        })
      }
      // all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)
      // 如果有其中一个被 reject 则返回第一个失败的promise
      static all(pArray: MyPromsie<any>[]) {
    
        const arr = Array(pArray.length);
        let i: number = 0;
        return new MyPromsie((resolve, reject) => {
          for (let index = 0; index < pArray.length; index++) {
            const promise = pArray[index];
            promise.then(val => {
              arr[index] = val;
              if (++i == pArray.length) {
                // 注意这里只能等异步调用返回结果之后才能resolve
                resolve(val);
              };
            }, reason => {
              console.log(reason)
              reject(reason);
            });
          }
        });
      }
    }
    
    interface IPromiseCBS {
      onFulfilled?: (val: any) => any;
      onRejected?: (reason: any) => any;
    }
    

    相关文章

      网友评论

          本文标题:手写promise

          本文链接:https://www.haomeiwen.com/subject/byolmctx.html