Promise 원리 & & 단순 실현

4765 단어

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에 있는 함수를 모두 대기열에 넣은 후에 실행하기 위해 setTimeout으로 넥스트의 논리적 패키지를
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 함수의 데이터는 이 Promise 대상resolve () 의 값이다
복잡하게 들린다. 리턴에 대한 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);
  });

보완 증가 약속.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);
})

좋은 웹페이지 즐겨찾기