promise 基本版(雏形)

function Promise(fn){
    //须要一个胜利时的回调
    var self = this
    var callback;
    //一个实例的要领,用来注册异步事宜
    self.then = function(done){
      callback = done;
    }
    // resolve 比 then 先实行 此时 callback 不存在
    // 所以 加一个 setTimeout 让resolve 函数在回调行列的末端
    // 为啥是0秒? 为啥处于回调行列末端?
    //(威望指南)假如以0毫秒的超时时刻来挪用setTimeout(),那末指定的函数不会马上执
    // 行,相反会把它放到行列中去,比及前面处于守候状况的事宜处置惩罚顺序悉数实行完成后,
    // 再“马上”挪用它。
    // 以下 体式格局写 提醒 resolve 未定义 触及闭包 作用域链的题目
    // setTimeout(function () {
    //   function resolve(value){
    //      callback && callback(value);
    //   }
    // }, 0)
    
    // 革新体式格局
    function resolve (value) {
      setTimeout(function () {
        callback && callback(value)
      }, 0)
    }
    fn(resolve);
  }

挪用promise

 // 实例化promise 回调函数fn实行胜利,并实行resolve函数,此时在回调行列内里增加一
 // 一个callback函数,并将resolve的参数通报出去。
 var promise = new Promise(function (resolve) {
    resolve(['3', 'aaa'])
 })
// 挪用then函数,并实行then回调,将then函数的参数done回调函数赋值给callback,
// 在回调行列内里(之前setTimeout增加进去的回调行列)实行then的回调函数
 promise.then(function (data) {
    console.log('data', data)
 })

然则以上体式格局写,我们永久都只能实行then中一个回调行列,这明显不硬朗。我们连系js设想形式的宣布–音讯定阅形式,再连系组织函数return this 知识点,轻微革新下:

function Promise(fn){
    //须要一个胜利时的回调
    var self = this
    self.deferreds = []; // then函数 回调行列 贮存容器
    //一个实例的要领,用来注册异步事宜
    self.then = function(onFulfilled){
      self.deferreds.push(onFulfilled)
      console.log('self.deferreds', self.deferreds) 
      // 挪用两次then 回调行列会逐一push
      return self // 链式挪用then
    }

    // 革新体式格局
    function resolve (value) {
      setTimeout(function () {
        self.deferreds.forEach(function (deferred) {
           deferred && deferred(value)
        })
      }, 0)
    }
    fn(resolve);
}

挪用then函数:

promise.then(function (data) {
    console.log('data', data)
}).then(function (resp) {
    console.log('resp', resp)
})

尽人皆知,组织函数Promise存在三个互斥状况:pending、fulfilled、rejected。Promise 对象的状况转变,只需两种能够:从 pending 变成 fulfilled 和从 pending 变成 rejected。只需这两种状况发作,状况就凝结了,不会再变了,会一向坚持这个效果。

所以:我们革新代码以下:

//略
// 初始化设置状况
self.status = 'pending'
//略
// ...
//略
// resolve的时刻 将状况置为
self.status = 'fulfilled'
//略

挪用实行,一样能够获得我们想要的数据。
然则
然则
然则
仅仅加上上面两行代码是不可的,细致明白加粗的那几个字,再连系我们的代码来看。
当我们挪用then函数的时刻,往我们then回调行列内里push回调函数,终究不论状况是pending
照样fulfilled,回调行列的函数都是被resolve函数触发的。如许就违犯了这句话:只需这两种状况发作,状况就凝结了,不会再变了,会一向坚持这个效果。
当我们状况转变成fulfilled,我们并没有真正转变状况,每次再从新实行的时刻,我们又从新走了一次then增加回调,然后由resolve来触发还调的历程。
所以then函数革新代码以下:

// 当status == 'pending'的时刻,我们才往then的回调行列push回调函数。
// 不然 直接实行回调函数,不会由resolve来触发then的回调函数实行。
if(self.status == 'pending') {
  self.deferreds.push(onFulfilled)
  return self
}
onFulfilled(value)
return self // 链式挪用then

所以到场value后,终究代码以下:
基本就完成了链式挪用then的一个带有pending 和 fulfilled 状况的Promise
后续会加上reject(), rejected以及最难明白的串行promise。

function Promise(fn){
    //须要一个胜利时的回调
    var self = this
    self.deferreds = []; // then函数 回调行列 贮存容器
    self.status = 'pending'
    self.value = null
    //一个实例的要领,用来注册异步事宜
    self.then = function(onFulfilled){
      if(self.status == 'pending') {
        self.deferreds.push(onFulfilled)
        return self
      }
      onFulfilled(self.value)
      return self // 链式挪用then
    }

    // 革新体式格局
    function resolve (newValue) {
      setTimeout(function () {
        self.value = newValue
        self.status = 'fulfilled'
        self.deferreds.forEach(function (deferred) {
           deferred && deferred(self.value)
        })
      }, 0)
    }
    fn(resolve);
 }

附录参考文献

    原文作者:健儿
    原文地址: https://segmentfault.com/a/1190000013039687
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞