• 手写promise第一天


    2020-09-22
    手写promise第一天
    status:
    • 用pending fulfilled rejected 3中情况分别对应 等待 成功 失败
    • 状态只能由等待改变为成功或者失败 且不可逆
    executor执行器:

    在promise的构造函数中接收一个执行器函数 这个函数是同步执行的

    这个执行器在执行时可以接收两个参数 分别是promise类中的resolve和reject

    resolve&reject:

    在执行器执行过程中,如果获取到需要的数据 那么执行resolve函数并将数据当做参数传入

    resolve函数会将状态status改为fulfilled并且把数据存入到value中

    当执行到resolve时 如果在成功回调函数队列中有回调函数 那么依次执行他们

    reject同理

    then:

    promise中的then函数 接收两个参数分别是成功和失败的回调

    同时新建一个新的promise对象 并且把这个then函数要做的事情作为 新promise对象的执行器函数传入

    在这个then函数中判断当前promise的状态 如果是成功 那么执行成功回调并将value传入

    成功回调函数可以返回一个值到 可以用一个变量接收作为新promise对象的resolve的参数传入

    如果当前promise的状态是rejected 那么同理调用reject方法

    如果状态是pending 说明当前promise还没有执行resolve或reject

    将then传入的成功回调和失败回调都存到对应的回调队列里 在resolve实行的时候再去调用

    resolvePromise处理器:

    由于用很多种情况都要去处理resolve 所以有必要提取出来作为一个单独的函数便于复用

    处理器中判断成功回调返回的值是普通值 那么可以直接执行新promise的resolve或reject方法

    如果返回值是一个promise对象 那么要用这个promise对象的then方法判断这个对象目前是成功还是失败 再调用对应方法

    如果返回值是一个promise对象且跟then方法中的promise对象相同 那么就死循环了 应该抛出一个错误

    总结:
    • 还没有处理then中的异步问题
    • 还没有实现promise.all等方法
    • then中逻辑还是有点乱 明天继续捋
    const PENDING = 'pengding';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    
    class MyPromise {
      status = PENDING; // 当前promise的状态
      value = undefined; // 当前promise的值
      reason = undefined; // 当前promise如果失败 失败的原因
    
      successCallbacks = []; // 如果异步 那么将回调存入到对应回调库中
      rejectCallbacks = [];
    
      // promise 的构造函数接受一个执行器 这个执行器会立即执行
      constructor(executor) {
        // 这个执行器接收两个参数 第一个参数是执行成功 第二个是失败
        // 在执行器执行的过程中如果resolve执行 那么这个promise成功
        executor(this.resolve, this.reject);
      }
    
      // 成功调用resolve方法 接收一个参数作为这个promise的返回值存在promise对象中
      resolve = data => {
        // 一旦status状态不是pending 那么就不再执行 保证状态不可逆
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        this.value = data; // 将promise成功获得的数据存在value中
        // 判断成功回调函数库中是否用未执行的函数 有的话依次执行
        while (this.successCallbacks.length) {
          this.successCallbacks.shift()(this.value);
        }
      }
    
      // 同resolve
      reject = reason => {
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        this.reason = reason;
        while (this.rejectCallbacks.length) this.rejectCallbacks.shift()(this.reason);
      }
    
      // then方法 接收两个函数作为参数 第一个是成功的回调
      then = (successCallback, rejectCallback) => {
        // then方法 返回的是一个新的promise对象 所以在执行then的时候 new一个新的promise
        // 同样的 这个新promise的执行器也会立即执行
        let promise2 = new MyPromise((resolve, reject) => {
          // 当执行到then方法时候 status已经是FULFILLED说明promise已经执行成功
          // 直接执行成功的回调 
          // 同时将成功回调的返回值传递给下一个promise的resolve方法
          if (this.status === FULFILLED) {
            setTimeout(() => {
              const thenReturnVal = successCallback(this.value);
              resolvePromise(promise2, thenReturnVal, resolve, reject);
            }, 0);
          } else if (this.status === REJECTED) {
            const thenRejectVal = rejectCallback(this.reason);
            resolvePromise(thenRejectVal, resolve, reject);
          } else {
            // 如果执行到then的时候状态还是pending 那么 先把成功和失败的回调都存入到对应的回调库中去
            // 第27行 如果resolve是异步的话 等异步结束接收到值再将回调函数从库中取出依次执行
            this.successCallbacks.push(successCallback);
            this.rejectCallbacks.push(rejectCallback);
          }
        });
        this.promise2 = promise2;
        return promise2;
      }
    }
    
    function resolvePromise(promise2, x, resolve, reject) {
      if (promise2 === x) {
        reject(new TypeError('重复调用自己了哦~'));
      }
      if (x instanceof MyPromise) {
        // 是promise对象 那需要调用Promise的then方法判断这个promise是否成功
        // 如果成功 调用resolve方法 并且把值传递下去 如果失败 调用reject并且把原因传递下去
        x.then(value => resolve(value), reason => reject(reason));
        // x.then(resolve, reject);
      } else {
        resolve(x);
      }
    }
    
    // (resolve, reject) => {resolve('666')} 是一个执行器函数 会立即执行
    // 两个参数分别是promise内部传入的
    const promise = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve(66666);
      }, 2000);
    })
    const promise33 = new MyPromise((resolve, reject) => {
      resolve('promise33')
    })
    
    // 第一个then调用时 传入两个回调函数
    // 第一个then函数内部立刻创建一个新的promise对象 并且then传入的两个函数
    // 和then中的所有逻辑代码都作为新promise对象的执行器立即执行
    // 如果promise成功 那么执行第一个也就是53行的successCallback
    let p1 = promise.then(data => {
      console.log(data);
      // 这个return会作为successCallback的返回值传入新的promise中
      // 在新promise调用resolve方法时 可以当做值传递给新promise的value
      setTimeout(() => {
        return promise33;
      }, 2000);
    }, reason => {
      console.log(reason);
    }) // 执行完第一个then后 会返回一个新的promise
    
    p1.then((thenReturnVal) => { // 再次调用then是调用新promise的then方法
      // 同时这个新promise的resolve方法接收上一个then方法successCallback的返回值作为value
      console.log(thenReturnVal);
      return 'then 3'
    }, (thenRejectVal) => {
      console.log(thenRejectVal);
    })
  • 相关阅读:
    Node.js github开源代码
    Node.js Base64 Encoding和Decoding
    图论500题
    gvim中的gvimrc和vimrc
    ubuntu 命令行卸载并清理软件
    vim复制到系统剪贴板
    Electron 主进程与渲染进程之间的通 信(同步通信、异步通信)
    Android 使用系统录制视频功能
    Electron 自定义软件顶部菜单、右键菜单以及绑定快捷键
    Electron remote 模块、通过 BrowserWindow 打开新窗口
  • 原文地址:https://www.cnblogs.com/lanpang9661/p/13715293.html
Copyright © 2020-2023  润新知