參考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); })