源碼取自:源碼博客javascript
源碼:html
class Promise2 { constructor(executor) { //executor執行器 this.status = 'pending'; //默認等待狀態 this.value = undefined; //成功的值 this.reason = undefined //失敗的原用 this.onResovleCallbacks = []; this.onRejectedCallbacks = []; let resolve = (value) => { if (this.status === 'pending') { this.status = 'resolved'; //成功 this.value = value; this.onResovleCallbacks.forEach(fn => fn()); } } let reject = (reason) => { if (this.status === 'pending') { this.status = 'rejected'; //失敗 this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()); } } try { executor(resolve, reject); //默認上執行器執行 } catch (e) { //捕獲到異常時,直接走失敗 reject(e); } } then (onFufilled, onRejected) { onFufilled = typeof onFufilled === 'function' ? onFufilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }; function resolvePromise (promise2, x, resolve, reject) { //x多是別人的 promise ,因此儘量的容許別人瞎寫 if (promise2 === x) { //返回的結果和promise是同一個,那麼永遠不會成功 return reject(new TypeError('循環引用')); } // let called; // 看x是否是promise。promise應該是一個對象 if (x != null && (typeof x === 'object' || typeof x === 'function')) { //多是promise try { let then = x.then; // 若是是對象 我就試着取一下then方法 若是有then,認爲它是promise if (typeof then === 'function') { // then是函數,是promise then.call(x, y => { // 成功和失敗只能調用一個 if (called) return; called = true; // resolve的結果依舊是promise 那就繼續解析 resolvePromise(promise2, y, resolve, reject); }, r => { if (called) return; called = true; reject(r); // 失敗了就失敗了 }) } else { resolve(x); // 直接成功便可 } } catch (e) { // 取then出錯了那就不要在繼續執行了 if (called) return; called = true; reject(e); } } else { //普通值 讓promise2直接變成成功態 resolve(x); } }; let promise2; //返回的新promise promise2 = new this.constructor((resolve, reject) => { if (this.status === 'resolved') { // setTimeout(() => { try { let x = onFufilled(this.value); //x是上一個promise返回值,多是一個普通值,也多是一個promise;x也多是別人的promise,咱們能夠寫一個方法,統一處理 resolvePromise(promise2, x, resolve, reject); //下一次then的實例promise2,此次返回值x,promise2的成功方法,promise2的失敗方法 } catch (e) { reject(e) } // }, 0); } if (this.status === 'rejected') { // setTimeout(() => { try { let x = onRejected(this.reason); // reject(x); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e) } // }, 0) } if (this.status === 'pending') { this.onResovleCallbacks.push(() => { // setTimeout(() => { try { let x = onFufilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } // }, 0) }); this.onRejectedCallbacks.push(() => { // setTimeout(() => { try { let x = onRejected(this.reason) resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } // }, 0) }) } }); return promise2; } catch (onRejected) { return this.then(null, onRejected); } finally (onFinally) { return this.then(function (value) { return Promise.resolve(onFinally(value)) }, function (reason) { return Promise.resolve(onFinally(reason)) }); } static resolve (data) { return new this((resovle) => { resovle(); }).then(_ => { return data; }) } static reject (data) { /* 與原生保持一致 */ return new this((resolve, reject) => { reject(data); }); /* 與Promise.resovle保持一致 */ return new this((resolve, reject) => { reject(); }).then(_ => { return data; }) } static all (arr) { arr = Object.prototype.toString.call([]) === "[object Array]" ? arr : [arr]; let length = arr.length; if (!length) return; return new this((resolve, reject) => { let result = []; let num = length; arr.forEach((item, index) => { /* 將item包裝爲promise */ return new this(r => r()) .then(_ => item) .then(_ => { result[index] = _; num--; num === 0? resolve(result):null; }, _ => { reject(_); }) }) }) } static race(arr){ arr = Object.prototype.toString.call([]) === "[object Array]" ? arr : [arr]; let length = arr.length; if (!length) return; return new this((resolve,reject)=>{ arr.forEach(item=>{ new this(r=>r()).then(_=>item) .then(_=>{ resolve(_); },_=>{ reject(_); }) }) }) } }
Promise:java
1. 爲了實現promise的鏈式調用,每一次的then,finally或catch後返回的都是一個全新的promise.promise
2.因爲1的緣由,狀態凝固也只在當前的promise中有效。函數
3.因爲1的緣由,promise中的resolveArrs的長度老是<=1,rejectArrs同理。this
4.then方法是promise的核心,then的回調的方法:
首先將返回值包裝爲一個promise,需排除回調方法不是當前promise自己,而後遞歸執行此promise,至爲普通返回值,直接resolve(onResolve),或reject(onReject)
5. catch,finally 爲then方法的特殊狀況prototype
6. 鏈式中的then爲微任務,須要所有早於當前週期中的全部setTimeout執行,全部不能加setTimeout;
若不加,同時會帶來另外一個問題:同一週期內此promise的then方法將所有提早於全部原生promise的then方法執行,不過不會出現即便有原生方法又使用此補丁的狀況。
二者比較,取後者影響更小code
7.Promise.resolve(data).then():data爲常量或Promise,data爲promise時, 狀態會被data所改變,then中獲取的爲promise執行的結果htm
8.Promise.reject(data):data爲常量或Promise,data爲promise時,狀態會被data所改變,then中獲取的爲promise自己對象