您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)Promise的實現(xiàn)思路是什么的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
Promise實現(xiàn)思路的個人理解
我一直覺得Promise雖然方便,但是它的寫法很怪,無法理解實現(xiàn)Promise的人是如何思考的。
不過最近我對于實現(xiàn)Promise的思考過程的有了一點點個人理解,特此記下。
感覺這篇文章我還是沒有把思路說清楚,時間緊張,就當(dāng)做一次記錄,回頭我要把這個過程在表達的在清楚一點。
用例
var p1 = new Promise2( ( resolve, reject ) => { setTimeout( () => { resolve( 'hello' ) }, 1000 ) } ) p1.then( res => { console.log( res + 'world' ) return res + 'world' } ) .then( res => { console.log( res + 'ziwei' ) return res + 'ziwei' } )
我覺得實現(xiàn)一個函數(shù)跟封裝組件類似,首先從以下幾點考慮:
1.這個函數(shù)用來做什么的?
2.接受哪些參數(shù)
3.返回值是什么
那么結(jié)合例子,和這幾個問題,我們得到
1.Promise是做異步流程控制的。通俗說就是,我希望某個函數(shù)暫時不執(zhí)行,等我希望它執(zhí)行時,就resolve一下,你這個函數(shù)在執(zhí)行。
2.構(gòu)造函數(shù)Promise接受一個函數(shù)。函數(shù)的參數(shù)是resolve,reject,resolve和reject也是函數(shù),是給用戶調(diào)用用的,當(dāng)用戶希望下一個異步執(zhí)行時,就調(diào)用resolve(0
3.返回一個promise實例。 promise實例都有一個then方法,而then方法也返回一個新的promise實例。由此就可以鏈?zhǔn)秸{(diào)用then了
先實現(xiàn)一個Promise(未實現(xiàn)then的鏈?zhǔn)秸{(diào)用)
1.Promise接受一個fn,不管其他,你覺得這個fn在內(nèi)部會干嘛?只能被調(diào)用唄,所以雖然不知道怎么搞,但是先調(diào)用一下fn(resolve,reject)
2.那這個resolve和reject不是用戶實現(xiàn)的,所以肯定是Promise開發(fā)者實現(xiàn)的,那我們要實現(xiàn)resolve和reject,它們是干嘛的,肯定用來是改變狀態(tài)的,所以定義this.state
3.resolve和reject也會接受用戶的參數(shù)吧,那我們就需要把這個參數(shù)用this.value緩存一下,將來then方法調(diào)用時,需要傳遞進去
4.then接受successFn和errorFn,這2個就是我們希望暫時不執(zhí)行的函數(shù)了。怎么做到暫時不執(zhí)行呢?就是聲明2個數(shù)組,把他們先存起來,將來resolve時,在調(diào)用
class Promise2 { constructor( fn ) { this.successFnArray = [] // 用來緩存successFn和errorFn this.errorFnArray = [] this.state = 'pendding' const resolve = ( res ) => { // resolve就做2件事情 1: 修改狀態(tài) 2:調(diào)用successFn this.state = 'fulfilled' this.value = res // this.value用來緩存data數(shù)據(jù)或者error this.successFnArray.forEach( successFn => { successFn( res ) } ) } const reject = ( err ) => { this.state = 'rejected' this.value = err this.errorFnArray.forEach( errorFn => { errorFn( res ) } ) } fn( resolve, reject ) // 先調(diào)用fn再說 } then( successFn, errorFn ) { switch ( this.state ) { case 'fulfilled': successFn( this.value ) // 如果調(diào)用了resolve,狀態(tài)就成了fulfilled,就會執(zhí)行successFn break case 'rejected': errorFn( this.value ) break case 'pendding': this.successFnArray.push( successFn ) // 如果還沒調(diào)用resolve,狀態(tài)就是pendding,就先把這些異步函數(shù)緩存起來。將來resole時調(diào)用 this.errorFnArray.push( errorFn ) } } } var p1 = new Promise2( ( resolve, reject ) => { setTimeout( () => { resolve( 'hello' ) }, 1000 ) } ) p1.then( res => { console.log( res + 'world' ) return res + 'world' } )
實現(xiàn)then鏈?zhǔn)秸{(diào)用
then的實現(xiàn),和JQ的鏈?zhǔn)秸{(diào)用不同,JQ是每次調(diào)用方法后,把this返回
而Promise規(guī)范要求,每次都要返回新的Promise對象
所以只需要把then方法修改一下。
這部分可能會迷惑,但是我想先說一下這里做了哪些事情,其實變化不大
之前的then做了哪些事情?
就是按照不同的state,調(diào)用了successFn或者errorFn,如果是pendding狀態(tài)就先緩存起來,等將來resolve時調(diào)用
鏈?zhǔn)絫hen有哪些改動?
首先then有了返回值,返回一個promise,而之前沒有返回值,return的是undefined
new Promise的過程,其實邏輯沒什么變化,唯一注意的,比如狀態(tài)fulfilled時,并非直接調(diào)用successFn
而是調(diào)用_successFn,而這個函數(shù)內(nèi)部本質(zhì)上還是調(diào)用successFn(),但同時把調(diào)用的返回值作為了resolve的參數(shù),調(diào)用了resolve()
因為當(dāng)successFn被調(diào)用,得到返回值時,就表示這個函數(shù)執(zhí)行完了,
就需要執(zhí)行下一個異步函數(shù)了,這樣下一個異步函數(shù)也會把successFn(res)的return值作為參數(shù)
then( successFn, errorFn ) { return new Promise2( ( resolve, reject ) => { const _successFn = res => { resolve(successFn(res)) } const _errorFn = err => { reject(errorFn(err)) } switch ( this.state ) { case 'fulfilled': _successFn( this.value ) break case 'rejected': _errorFn( this.value ) break case 'pendding': this.successFnArray.push( _successFn ) this.errorFnArray.push( _errorFn ) } } ) }
感謝各位的閱讀!關(guān)于Promise的實現(xiàn)思路是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。