继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

简单实现 ES6 Promise

DIEA
关注TA
已关注
手记 279
粉丝 63
获赞 386
最近在使用ES6,所以手动实现了一个简单的ES6 Promise对象来玩玩(如果有错误的地方,希望大家能够不吝赐教)

一个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和rejectvar nextResolve = nullvar nextReject = null// 记录then方法的参数,onFulfilled和onRejectedvar asynconFulfilled = nullvar 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方法调用,所以我们可以把这段代码抽象为一个函数
resolvereject的原理相同,只要注意如果不是function 的话需要执行reject


onFulfilledonRejected只有在[执行环境]堆栈仅包含平台代码时才可被调用
所以将上述begin-end之间的代码放到seTimeout中执行(浏览器环境)

function resolve(data) {  // 记录onFulfilled的执行结果
  var parmise  // 改变状态
  state = true
  param = data  // 执行记录的onFulfilled
  window.setTimeout(function () {    // begin--------------
    // 上述代码
    // ---------------end
  }, 0)
}

下面是完整代码

// 简单实现ES6 Promisefunction 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')

完毕!



作者:LitCigar
链接:https://www.jianshu.com/p/69dcb2f415dc

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP