Promise原理 && 简单实现

Promise原理

参考https://github.com/chunpu/promise/blob/master/promise.js

个人认为原博的实现有点问题 在next函数的实现上, 会导致无限的调用

看看一般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调用

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中的逻辑包裹

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()的值

听起来很复杂 针对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);
})
posted @ 2016-02-18 23:57  cart55free99  阅读(580)  评论(0编辑  收藏  举报