Promise原理 && 簡單實現

Promise原理

參考https://github.com/chunpu/promise/blob/master/promise.jsgit

我的認爲原博的實現有點問題 在next函數的實現上, 會致使無限的調用github

看看通常Promise的用法數組

promise = new Promise(function(resolve, reject) {
  //...
    resolve(1);
  //...
})
.then(function(val){}, functioin(err){})
.then(function(val){}, functioin(err){})

顯然要實現的功能是這樣的
Promise對象有then方法
Promise對象接受一個參數fn(resolve, reject)
Promise能夠連續的then調用promise

function Promise(resolver) {
  var queue = [];//鏈式調用數組
  resolver(resolve, reject);

  //state 0 是resolve
  function next(state, val){
    var arr;
    if(arr = queue.shift()){
      arr[state](val);
    }
  }

  function resolve(x){
    next(0, x)
  }
  function reject(reason){
    next(1, reason);
  }

  //Promise最明顯的特徵 是能夠then  then接收兩個參數
  //then就是將傳入的函數放入隊列中
  this.then = function(resolve, reject){
    queue.push([resolve, reject]); //resovle  reject  這兩個參數也都是函數
  }
}


var p = new Promise(function(resolve){
  resolve('ok')
})

p.then(function(x){
  console.log(x);
})

有個問題 那就是建立一個Promise對象的時候就調用了 resolver(resolve, reject); 也就是調用了resolve('ok') 也就是調用了next 也就是使queue函數出隊列並執行函數

可是這個時候 queue 尚未push任何值 執行不能繼續 畢竟這個是在Promise對象完成建立以後才調用then測試

爲了使next在then中的函數所有進到隊列以後再執行 用一個setTimeout把 next中的邏輯包裹this

function Promise(resolver) {
  var queue = [];
  resolver(resolve, reject);

  function next(state, val){
    var arr;
    //爲了使resolve晚於 then 執行  暫時用一個setTimeout
    setTimeout(function(){
      if(arr = queue.shift()){
        arr[state](val);
      }
    }, 0);
  }

  function resolve(x){
      next(0, x);
  }
  function reject(reason){
      next(1, reason);
  }

  this.then = function(resolve, reject){
    queue.push([resolve, reject]);
  }
}

var p = new Promise(function(resolve){
  setTimeout(function(){
    resolve('ok')
  },1200);
}).then(function(data){
  console.log(data);
})

不過咱們知在一個then中 return 可能不單單是一個簡單地的value , 有可能再次返回一個Promise對象 而下一個then中resolve函數的的data是這個Promise對象resolve()的值code

聽起來很複雜 針對return一個Promise對象的狀況 就是調用這個對象的then
而後再次進入next 而next的參數就是返回的Promise對象的resolve的值對象

function Promise(resolver) {
  var queue = []; //鏈式調用數組
  resolver(resolve, reject);

  //state 0 是resolve
  function next(state, val) {
    var arr;
    var chainRs;
    setTimeout(function() {
      if (arr = queue.shift()) {
        chainRs = arr[state](val);
        if(!chainRs) return;
        //某一個resolve函數返回的又是一個Promise對象
        if (chainRs && typeof chainRs.then == 'function') {
          chainRs.then(resolve, reject);
        } else {
          //resolve函數返回一個普通的值
          resolve(chainRs) //.then(resolve, reject);
        }
      }
    }, 0);
  }

  function resolve(x) {
    next(0, x);
  }

  function reject(reason) {
    next(1, reason);
  }
  //Promise最明顯的特徵 是能夠then  then接收兩個參數
  //then就是將傳入的函數放入隊列中
  this.then = function(resolve, reject) {
    queue.push([resolve, reject]); //resovle  reject  這兩個參數也都是函數
    return this;
  }
}
Promise.resolve = Promise.cast = function(x) {
  return new Promise(function(resolve) {
    resolve(x);
  })
}

測試隊列

var p = new Promise(function(resolve) {
    setTimeout(function() {
      resolve('ok')
    }, 1200);
  }).then(function(data) {
    console.log(data);
    // return 555;
    return new Promise(function(resolve){
      setTimeout(function(){
        resolve('wahaha');
      }, 2200);
    })
  })
  .then(function(data) {
    console.log('2nd then', data);
    return 666;
  })
  .then(function(data) {
    console.log('3rd then', data);
  });

完善 增長Promise.all() Promise.resolve()

Promise.resolve = Promise.cast = function(x) {
  return new Promise(function(resolve) {
    resolve(x);
  })
}

Promise.all = function(promises){
  var len = promises.length;
  var results = [];
  return new Promise(function(resolve){
    promises.forEach(function(p, i){
      p.then(function(data){
          results[i] = data;
          len--;
          if(len == 0){
            resolve(results);
          }
      }, function(err){
        console.log(err);
      });
    });
  });
}


//=================================

Promise.resolve(999)
.then(function(data){
  console.log(data);
  return new Promise(function(resolve, reject){
    // resolve('xixi');
    reject('xixi');
  })
}).then(function(data){
  console.log(data);
},function(err){
  console.log(err);
})

Promise.all([
new Promise(function(resolve){
  setTimeout(function(){
    resolve(111);
  }, 1000);

}),
new Promise(function(resolve){
  resolve(222);
})

]).then(function(results){
  console.log(results);
})
相關文章
相關標籤/搜索