ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

手写promise第一天

2020-09-22 22:31:49  阅读:223  来源: 互联网

标签:执行器 resolve 函数 第一天 promise reject 手写 执行


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);
})

 

标签:执行器,resolve,函数,第一天,promise,reject,手写,执行
来源: https://www.cnblogs.com/lanpang9661/p/13715293.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有