手写简单版 Promise

Promise 是异步编程的的最终结果,Promise 有三种状态: pending、fulfilled、rejected。只有异步操作的结果可以决定当前是哪一种状态,其它任何操作都无法改变。与之进行交互的方式主要是 then 方法,该方法注册了两个回调函数,用于接收 Promise 的终值或 promise 不能执行的原因。 当 then 中的回调函数不是函数的时候,会忽略当前 then 方法,使用前一个 then 中的值,如果 then 中的回调函数没有返回值,则下一个 then 的值默认 undefined,每个 then 只可能使用前一个 then 的返回值,并且调用次数不能超过一次。

Promise 的设计局限性造成了一个让人很容易中招的陷阱,那就是 Promise 链中的错误很容易被无意中默默忽略掉。

// 首先定义 Promise 的三个状态
const PENDING = "pending";
const RESOVLED = "resolved";
const REJECTED = "rejected";

/*
*创建一个 Promise 函数,接受一个函数参数
*开始时promise状态为 pending,value 值用来保存 resolve 或 reject 中传入的值
*CallBacks 用来保存 then 中的回调函数
*/
function Promise(fn) {
  const that = this;
  that.state = PENDING;
  that.value = null;
  that.resolveCallBacks = [];
  that.rejectedCallBacks = [];
  
  // 执行 fn 函数
  try {
    fn(resolve, reject)
  } catch(err) {
    reject(err);
  }
  
  // fn 中的 resolve, reject 分别是两个函数
  function resolve(value) {
    // 首先判断状态是否为 pending, 只有状态为 pending 时才能改变状态
    if (that.state == PENDING) {
      that.state = RESOLVED;
      that.value = value;
      // 执行 then 中的回调函数
      that.resolveCallBacks.map(cb => (that.value = cb(that.value)))
    }
  }
  
  function reject(value) {
    if (that.state == PENDING) {
      that.state = REJECTED;
      that.value = value;
      that.rejectCallBacks.map(cb => (that.value = cb(that.value)))
    }
  }
}

// 原型上的 then 方法
Promise.prototype.then = function(onFulfilled, onRejected) {
  const that = this;
  // 需要判断传入的参数是否为函数,如果不是函数需要创建一个函数赋值给对应参数,同时实现透传,也就开头所说的传入不是函数的问题
  onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : v => v;
  onRejected = typeof onRejected == 'function' ? onRejected : v => { throw v }
  
  switch(that.state) {
    case PENDING:
      that.resolveCallBacks.push(onFulfilled);
      that.rejectCallBacks.push(onRejected);
      break;
    case RESLOVED:
      that.value = onFulfilled(that.value);
      break;
    case REJECTED:
      that.value = onRejeted(that.value);
      break;
    defalut: 
      break;
  }
  return that;
}

// test
new Promise(function(resolve, reject) {
  setTimeout(() => {
    resolve(1);
  }, 10)
}).then(res => {
  console.log(res) // 1
  return 2;
}).then(res => {
  console.log(res);  // 2
})

你可能感兴趣的:(Web开发)