Promise原理解析,使用ES5实现Promise

Promise

js的单线程特性导致大量的异步操作,异步操作我们通常使用函数回调的方式实现。大量的函数回调会产生我们的毁掉地狱,降低代码的可读性和可维护性。

为了解决这些问题,先后出现了Promise函数、Generator函数和async函数。目前Promise配合async/await成为了主流。

Promise本质上并没有改变异步操作,只是让我们可以用同步的代码写法去书写异步操作。增加代码的可读性。

Promise是ES6中确定的,今天我们就使用ES5的写法,手动实现自己的Promise,以求彻底掌握Promise的核心原理。今天我们只封装实现Promise的基本功能。

先看一下在ES6中我们是如何使用Promise的

let promiseFn = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(111)
  }, 1000)
});
promiseFn.then(res => {
  console.log(res) // res === 111
})

// 使用async/await
async function promiseFn () {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(111)
    }, 1000)
  })         
}
 let res = await promiseFn() // res === 111

Promise规范

Promise规范的原文地址

Promise规范的中文翻译地址

里面详细介绍了Promise的各种术语、定义和规范。其中最需要理解的就是Promise的三种状态以及其中的状态变化。“等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)”。

状态改变不可逆,只能Pending --> Fulfilled 或者 Pending --> Rejected

预备

使用status存储Promise状态(pending、fulfilled、rejected)
使用value存储resolve的数据
使用err存储reject的错误信息
使用原型链继承的方式创建then函数
使用onFulfilledArr存储将要执行的resolve函数
使用onRejectedArr存储将要执行的reject函数

创建 MyPromise构造函数

// 创建 MyPromise构造函数
function MyPromise (fn) {
  let self = this;
  this.value = null; // 存储resolve数据
  this.status = 'pending'; // 存储状态
  this.err = null; // 存储reject错误信息
  this.onFulfilledArr = []; // 存储将要执行的resolve函数
  this.onRejectedArr = []; // 存储将要执行的reject函数
  function resolveFn (val) { // resolve()时执行的函数
    if (self.status === 'pending') { // 只用pending状态才能继续进行
      self.value = val; // 存储数据
      self.status = 'fulfilled'; // 改变状态
      // 逐个调用then()函数
      self.onFulfilledArr.forEach(function(thenFn) {
          thenFn(self.value);
      });
    }
  }
  function rejectFn(errMsg) { // reject()时执行的函数
    if (self.status === 'pending') {
      self.err = errMsg;
      self.status = 'rejected';
       self.onRejectedArr.forEach(function(catchFn) {
        catchFn(self.err);
      });
    }
  }
  try {
    fn(resolveFn, rejectFn);
  } catch (e) {
    rejectFn(e);
  }
}

实现then()函数

创建好了Promise构造函数下一步创建then()函数

MyPromise.prototype.then = function(onFulfilled, onRejected) {
  // 如果当前处于pending状态,就将函数压入对应数组
  var self = this;
  if (self.status === 'pending') {
    self.onFulfilledArr.push(onFulfilled);
    self.onRejectedArr.push(onRejected);
  }
  // fulfilled状态就执行onFulfilled()方法
  if (self.status === 'fulfilled') {
    onFulfilled(self.value);
  }
  // onFulfilled状态就要执行onRejected()函数
  if (self.status === 'rejected') {
    onRejected(self.err);
  }
  return this; // return this是链式调用关键
};

到此我们就实现了自己的myPromise()方法。最关键的还是Promise的三种状态,理解了三种状态的切换就基本掌握了Promise。

你可能感兴趣的:(Promise原理解析,使用ES5实现Promise)