本文博客原文地址git
咱們在開發過程當中大多會用到promise
,想必你們對promise
的使用都很熟練了,今天咱們就來實現一個簡單的promise
,實現的效果若有出入還往指正。es6
咱們先來梳理一下總體的結果,以便後續好操做github
class MyPromise { constructor(fn){ } resolve(){ } then(){ } reject(){ } catch(){ } }
摘抄至 http://es6.ruanyifeng.com/#do...
Promise
對象有如下兩個特色。promise
(1)對象的狀態不受外界影響。Promise對象表明一個異步操做,有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。這也是Promise這個名字的由來,它的英語意思就是「承諾」,表示其餘手段沒法改變。異步
(2)一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果。Promise對象的狀態改變,只有兩種可能:從pending變爲fulfilled和從pending變爲rejected。只要這兩種狀況發生,狀態就凝固了,不會再變了,會一直保持這個結果,這時就稱爲 resolved(已定型)。若是改變已經發生了,你再對Promise對象添加回調函數,也會當即獲得這個結果。這與事件(Event)徹底不一樣,事件的特色是,若是你錯過了它,再去監聽,是得不到結果的。函數
總結一下就是promise有三種狀態:pending(進行中)、fulfilled(已成功)和rejected(已失敗),還有就是狀態的改變只能是pending -> fulfilled 或者 pending -> rejected,這些很重要測試
如今咱們開始實現構造函數this
class MyPromise { constructor(fn){ if(typeof fn !== 'function') { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = 'pending'; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } ... }
構造函數接收一個參數fn
,且這個參數必須是一個函數,由於咱們通常這樣使用new Promise((resolve,reject)=>{})
;
而後初始化一下promise的狀態,默認開始爲pending,初始化value的值。fn
接收兩個參數,resolve
、reject
debug
class MyPromise { constructor(fn){ if(typeof fn !== 'function') { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = 'pending'; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } resolve(value){ if(this.state !== 'pending') return; this.state = 'fulfilled'; this.value = value } ... }
當resolve
執行,接收到一個值以後;狀態就由 pending
-> fulfilled
;當前的值爲接收的值code
class MyPromise { constructor(fn){ if(typeof fn !== 'function') { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = 'pending'; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } resolve(value){ if(this.state !== 'pending') return; this.state = 'fulfilled'; this.value = value } reject(reason){ if(this.state !== 'pending') return; this.state = 'rejected'; this.value = reason } }
當reject
執行,接收到一個值以後;狀態就由 pending
-> rejected
;當前的值爲接收的值
class MyPromise { constructor(fn){ if(typeof fn !== 'function') { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = 'pending'; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } resolve(value){ if(this.state !== 'pending') return; this.state = 'fulfilled'; this.value = value } reject(reason){ if(this.state !== 'pending') return; this.state = 'rejected'; this.value = reason } then(fulfilled,rejected){ if (typeof fulfilled !== 'function' && typeof rejected !== 'function' ) { return this; } if (typeof fulfilled !== 'function' && this.state === 'fulfilled' || typeof rejected !== 'function' && this.state === 'rejected') { return this; } return new MyPromise((resolve,reject)=>{ if(fulfilled && typeof fulfilled === 'function' && this.state === 'fulfilled'){ let result = fulfilled(this.value); if(result && typeof result.then === 'function'){ return result.then(resolve,reject) }else{ resolve(result) } } if(rejected && typeof rejected === 'function' && this.state === 'rejected'){ let result = rejected(this.value); if(result && typeof result.then === 'function'){ return result.then(resolve,reject) }else{ resolve(result) } } }) } }
then
的實現比較關鍵,首先有兩個判斷,第一個判斷傳的兩個參數是否都是函數,若是部不是return this
執行下一步操做。
第二個判斷的做用是,好比,如今狀態從pending
-> rejected
;可是中間代碼中有許多個.then
的操做,咱們須要跳過這些操做執行.catch
的代碼。以下面的代碼,執行結果只會打印1
new Promise((resolve,reject)=>{ reject(1) }).then(()=>{ console.log(2) }).then(()=>{ console.log(3) }).catch((e)=>{ console.log(e) })
咱們繼續,接下來看到的是返回了一個新的promise
,真正then
的實現的確都是返回一個promise
實例。這裏很少說
下面有兩個判斷,做用是判斷是rejected
仍是fulfilled
,首先看fulfilled
,若是是fulfilled
的話,首先執行fulfilled
函數,並把當前的value
值傳過去,也就是下面這步操做,res
就是傳過去的value
值,並執行了(res)=>{console.log(res)}
這段代碼;執行完成以後咱們獲得了result
;也就是2
這個結果,下面就是判斷當前結果是不是一個promise
實例了,也就是下面註釋了的狀況,如今咱們直接執行resolve(result)
;
new Promise((resolve,reject)=>{ resolve(1) }).then((res)=>{ console.log(res) return 2 //return new Promise(resolve=>{}) })
剩下的就很少說了,能夠debugger
看看執行結果
class MyPromise { ... catch(rejected){ return this.then(null,rejected) } }
class MyPromise { constructor(fn){ if(typeof fn !== 'function') { throw new TypeError(`MyPromise fn ${fn} is not a function`) } this.state = 'pending'; this.value = void 0; fn(this.resolve.bind(this),this.reject.bind(this)) } resolve(value){ if(this.state !== 'pending') return; this.state = 'fulfilled'; this.value = value } reject(reason){ if(this.state !== 'pending') return; this.state = 'rejected'; this.value = reason } then(fulfilled,rejected){ if (typeof fulfilled !== 'function' && typeof rejected !== 'function' ) { return this; } if (typeof fulfilled !== 'function' && this.state === 'fulfilled' || typeof rejected !== 'function' && this.state === 'rejected') { return this; } return new MyPromise((resolve,reject)=>{ if(fulfilled && typeof fulfilled === 'function' && this.state === 'fulfilled'){ let result = fulfilled(this.value); if(result && typeof result.then === 'function'){ return result.then(resolve,reject) }else{ resolve(result) } } if(rejected && typeof rejected === 'function' && this.state === 'rejected'){ let result = rejected(this.value); if(result && typeof result.then === 'function'){ return result.then(resolve,reject) }else{ resolve(result) } } }) } catch(rejected){ return this.then(null,rejected) } }
new MyPromise((resolve,reject)=>{ console.log(1); //reject(2) resolve(2) console.log(3) setTimeout(()=>{console.log(4)},0) }).then(res=>{ console.log(res) return new MyPromise((resolve,reject)=>{ resolve(5) }).then(res=>{ return res }) }).then(res=>{ console.log(res) }).catch(e=>{ console.log('e',e) }) 執行結果: > 1 > 3 > 2 > 5 > 4
原生promise
new Promise((resolve,reject)=>{ console.log(1); //reject(2) resolve(2) console.log(3) setTimeout(()=>{console.log(4)},0) }).then(res=>{ console.log(res) return new Promise((resolve,reject)=>{ resolve(5) }).then(res=>{ return res }) }).then(res=>{ console.log(res) }).catch(e=>{ console.log('e',e) }) 執行結果: > 1 > 3 > 2 > 5 > 4