实现的一个简单的ES6 Promise(如果有错误的地方,希望大家能够不吝赐教)

仅实现Promise及.then方法
最下方有完整代码

开始

一个promise对象接收的是一个callback
这个callback接收两个参数(resolve,reject)
当我们在callback内执行resolvereject的时候,就会调用Promise内定义的 resolvereject函数
然后,resolvereject函数会改变Promise的状态
所以它应该是像下面这样的
function MyPromise(callback) {
  // 保存this值
  var self = this
  // 记录状态null为pending,true为resolved,false为reject
  var state = null
  // 记录resolve的参数
  var param = null

  // 执行传入的callback并改变promise对象状态
  callback(resolve, reject)
  // resolve方法
  function resolve(data) {
    // 改变状态
    state = true
    param = data
  }

  // reject方法
  function reject(err) {
    state = false
    param = err
  }
}
但没有then方法的Promise对象是不完整的(完全没有用)
所以我们需要一个then方法,要记住then方法返回的也是一个promise对象
then方法接收两个可选的参数(onFulfilled, onRejected)(我们可以先忽略可选两个字)
then方法传进来的参数必须是函数,如果不是就要忽略(PromiseA+规范)(我们可以也先忽略这句话)
  this.then = function (onFulfilled, onRejected) {
    // 返回一个新的promise对象
    return new self.constructor(function (resolve, reject) {
      // then
    })
  }
接下来就是then方法的具体实现了
then方法中onFulfilled, onRejected的返回值会作为新promise的执行结果

onFulfilled, onRejected这两个函数要在promise的状态变为pending或resolved的时候才能分别执行
所以如果promise方法状态为resolvedrejected的话,我们就可以直接在then方法中执行resolve(onFulfilled(param))reject(onRejected(param))

  this.then = function (onFulfilled, onRejected) {
    // 返回一个新的promise对象
    return new self.constructor(function (resolve, reject) {
       if (state === true) {
        // param是promise对象完成后的结果
        resolve(onFulfilled(param))
      } else if (state === false) {
        reject(onRejected(param))
      } else {
        // 没有执行完毕,怎么办
      }
    })
  }
但如果promise的状态为pending
由于原始promise的状态我们是无法动态获取的,因此我们就需要在他执行状态改变的时候同时执行onFulfilledonRejected方法
我们可以把这个方法放在原始promise对象的resolvereject方法中执行
因此我们要在promise的对象定义中添加四个参数,分别记录onFulfilledonRejected,以及then方法返回的新promise对象的resolvereject
然后如果执行then方法的时候promise对象的状态为pending的话,就将上述四个参数记录起来
// then方法返回的promise对象的resolve和reject
var nextResolve = null
var nextReject = null
// 记录then方法的参数,onFulfilled和onRejected
var asynconFulfilled = null
var asynconRejected = null

//then方法
this.then = function (onFulfilled, onRejected) {
    // 返回一个新的promise对象
    return new self.constructor(function (resolve, reject) {
      if (state === true) {
        // param是promise对象完成后的结果
        resolve(onFulfilled(param))
      } else if (state === false) {
        reject(onRejected(param))
      } else {
        nextResolve = resolve
        nextReject = reject
        asynconFulfilled = onFulfilled
        asynconRejected = onRejected
      }
    })
  }
接下来就是原始promise中的resolvereject的重新实现
 // resolve方法
  function resolve(data) {
    // 改变状态
    state = true
    param = data
    nextResolve(asynconFulfilled(param))
  }

  // reject方法
  function reject(err) {
    state = false
    param = err
    nextReject(asynconRejected(param))
  }
很简单不是吗
我们继续
上述实现我们一直没有考虑一个很重要的情况,如果then方法返回的还是一个promise对象,那么如果我们后边还有then方法的话就要等待前一个then方法中的promise对象的状态从pending变为完成
这要怎么做呢
什么时候可以认为then方法返回的promise对象执行完毕了呢,这里我们就要用到then方法(@_@,边写边用...),
resolve方法为例
var self = this
// resolve方法
function resolve(data) {
  // 记录onFulfilled的执行结果
  let parmise
  // 改变状态
  state = true
  param = data
  // 执行记录的onFulfilled
  parmise = asynconFulfilled(param)
  if(parmise === undefined){
    // 如果parmise为undefined,就不能解析parmise.constructor
  } else if (parmise.constructor === self.constructor) {
    // 等待传递进来的promise对象执行完毕,然后根据传递进来的promise对象的状态执行resolve或reject
    // 注意,这个param是形参,在then方法的promise中执行
    promise.then(function (param) {
      resolve(param)
    }, function (param) {
      reject(param)
    })
  } else {
    // 这个是前边的then返回的不是promise对象的情况
    resolve(promise)
  }
}
前面我们忽略了两点 (then方法接收两个可选的参数(onFulfilled, onRejected)) 和 (then方法传进来的参数必须是函数,如果不是就要忽略)
var self = this
// resolve方法
function resolve(data) {
  // 记录onFulfilled的执行结果
  var parmise
  // 改变状态
  state = true
  param = data
  // 执行记录的onFulfilled
  // begin--------------
  if (typeof onFulfilled === 'function') {
    promise = onFulfilled(param)
    if (promise === undefined) {
      // 待补充
    } else if (promise.constructor === self.constructor) {
      // 注意,这个param是形参,在then方法的promise中执行
      promise.then(function (param) {
        resolve(param)
      }, function (param) {
        reject(param)
      })
    } else {
      reject(promise)
    }
  } else {
    // 如果onFulfilled不是function,忽略,直接resolve或reject
    resolve(param)
  }
  // ---------------end
}
上面begin到end之间的代码还要在then方法调用,所以我们可以把这段代码抽象为一个函数
resolve reject的原理相同,只要注意如果不是function 的话需要执行reject

onFulfilled和 onRejected只有在[执行环境]堆栈仅包含平台代码时才可被调用
所以将上述begin-end之间的代码放到seTimeout中执行(浏览器环境)
function resolve(data) {
  // 记录onFulfilled的执行结果
  var parmise
  // 改变状态
  state = true
  param = data
  // 执行记录的onFulfilled
  window.setTimeout(function () {
    // begin--------------
    // 上述代码
    // ---------------end
  }, 0)
}
下面是完整代码
注:没有实现正确的事件循环
// 简单实现ES6 Promise
function MyPromise(callback) {
  // 保存this值
  var self = this
  // 记录状态null为pending,true为resolved,false为reject
  var state = null
  // 记录resolve的参数
  var param = null
  // then方法返回的promise对象的resolve和reject
  var nextResolve = null
  var nextReject = null
  // 记录then方法的参数,onFulfilled和onRejected
  var asynconFulfilled = null
  var asynconRejected = null

  // 执行并改变promise对象状态
  callback(resolve, reject)
  // then方法
  this.then = function (onFulfilled, onRejected) {
    // 返回一个新的promise对象
    return new self.constructor(function (resolve, reject) {
      // 判断异步代码是否执行完毕(是否resolve或reject)
      // 若执行完毕就在then方法中立即执行,否则将四个参数记录下来,等待state就绪后再执行doAsyn*函数
      if (state === true) {
        doAsynconFulfilled(onFulfilled, resolve, reject)
      } else if (state === false) {
        doAsynconRejected(onRejected, resolve, reject)
      } else {
        nextResolve = resolve
        nextReject = reject
        asynconFulfilled = onFulfilled
        asynconRejected = onRejected
      }
    })
  }
  // resolve方法
  function resolve(data) {
    // 改变状态
    state = true
    param = data
    if(nextResolve){
        doAsynconFulfilled(asynconFulfilled, nextResolve, nextReject)
    }
  }

  // reject方法
  function reject(err) {
    state = false
    param = err
    if(nextReject){
        doAsynconRejected(asynconRejected, nextResolve, nextReject)
    }
  }

  // 核心方法(我觉得是)

  function doAsynconFulfilled(onFulfilled, resolve, reject) {
      window.setTimeout(function () {
        // 判断onFulfilled是否为function,不是则忽略
        if (typeof onFulfilled === 'function') {
          // 执行onFulfilled方法获取返回值promise()
          let promise = onFulfilled(param)
          // 如果promise为undefined 执行 if
          // 如果promise为MyPromise对象 执行 else if
          // 如果promise为非MyPromise对象 执行 else
          if (promise === undefined) {
            resolve(param)
            // 待补充
          } else if (promise.constructor === self.constructor) {
            // 等待传递进来的promise对象执行完毕,然后根据传递进来的promise对象的状态执行resolve或reject
            promise.then(function (param) {
              resolve(param)
            }, function (param) {
              reject(param)
            })
          } else {
            // 执行then方法返回的对象的resolve
            resolve(promise)
          }
        } else {
          // 传递参数
          resolve(param)
        }
      }, 0)
    
  }

  function doAsynconRejected(onRejected, resolve, reject) {
    window.setTimeout(function () {
        if (typeof onRejected === 'function') {
          let promise = onRejected(param)
          if (promise === undefined) {
            reject(param)
            // 待补充
          } else if (promise.constructor === self.constructor) {
            promise.then(function (param) {
              resolve(param)
            }, function (param) {
              reject(param)
            })
          } else {
            reject(promise)
          }
        } else {
          // 传递错误信息
          reject(param)
        }
    }, 0)
  }
}
// 测试使用
var b = function (message) {
    return new MyPromise(function (resolve, reject) {
        document.body.onclick = function () {
            resolve('click:' + message)
        }
    })
}
var a = new MyPromise(function (resolve, reject) {
  resolve(123)
}).then(function (message) {
    return b(message)
}).then().then(function (message) {
    console.log('final:' + message)
},function (err) {
    console.log('final:' + err)
})
console.log('window')
当然还有Promise.all等方法。
完毕!

bello
5 声望1 粉丝