首頁  >  文章  >  web前端  >  Promise實現想法的深入分析(程式碼範例)

Promise實現想法的深入分析(程式碼範例)

不言
不言轉載
2018-11-24 14:09:221882瀏覽

這篇文章帶給大家的內容是關於Promise實現思路的深入分析(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

Promise實現想法的個人理解

我一直覺得Promise雖然方便,但是它的寫法很怪,無法理解實現Promise的人是如何思考的。

不過最近我對於實現Promise的思考過程的有了一點點個人理解,特此記下。

感覺這篇文章我還是沒有把思路說清楚,時間緊張,就當做一次記錄,回頭我要把這個過程在表達的在清楚一點。

用例

   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'
            } )

我覺得實作一個函數跟封裝元件類似,首先從以下幾點考慮:

  • 1 .這個函數用來做什麼的?

  • 2.接受哪些參數

  • 3.傳回值是什麼

那麼結合例子,和這幾個問題,我們得到

  • 1.Promise是做非同步流程控制的。 通俗說就是,我希望某個函數暫時不執行,等我希望它執行時,就resolve一下,你這個函數在執行。

  • 2.建構子Promise接受一個函式。 函數的參數是resolve,reject,resolve和reject也是函數,是給使用者呼叫用的,當使用者希望下一個非同步執行時,就呼叫resolve(0

  • # 3.傳回一個promise實例。 promise實例都有一個then方法,而then方法也傳回一個新的promise實例。由此就可以鍊式呼叫then了

#先實作一個Promise(未實作then的鍊式呼叫)
  • #1.Promise接受一個fn,不管其他,你覺得這個fn在內部會幹嘛?只能被呼叫唄,所以雖然不知道怎麼搞,但是先呼叫一下fn(resolve,reject)

  • 2.那這個resolve和reject不是用戶實現的,所以肯定是Promise開發者實現的,那我們要實作resolve和reject,它們是乾嘛的,一定用來是改變狀態的,所以定義this.state

  • 3.resolve和reject也會接受使用者的參數吧,那我們就需要把這個參數用this.value快取一下,將來then方法呼叫時,需要傳遞進去

  • 4.then接受successFn和errorFn,這2個就是我們希望暫時不執行的函數了。怎麼做到暫時不執行呢?就是宣告2個數組,把他們先存起來,將來resolve時,在呼叫

        class Promise2 {
            constructor( fn ) {
                this.successFnArray = []  // 用来缓存successFn和errorFn
                this.errorFnArray = []
                this.state = 'pendding'
                const resolve = ( res ) => {      // resolve就做2件事情  1: 修改状态 2:调用successFn
                    this.state = 'fulfilled'
                    this.value = res         // this.value用来缓存data数据或者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 )   // 先调用fn再说
            }

            then( successFn, errorFn ) {
                switch ( this.state ) {
                    case 'fulfilled':
                        successFn( this.value )        // 如果调用了resolve,状态就成了fulfilled,就会执行successFn
                        break
                    case 'rejected':
                        errorFn( this.value )
                        break
                    case 'pendding':
                        this.successFnArray.push( successFn )   // 如果还没调用resolve,状态就是pendding,就先把这些异步函数缓存起来。将来resole时调用
                        this.errorFnArray.push( errorFn )
                }
            }
        }

        var p1 = new Promise2( ( resolve, reject ) => {
            setTimeout( () => {
                resolve( 'hello' )
            }, 1000 )

        } )

        p1.then( res => {
            console.log( res + 'world' )
            return res + 'world'
        } )

實作then鍊式呼叫

then的實現,和JQ的鍊式呼叫不同,JQ是每次呼叫方法後,把this回傳

而Promise規範要求,每次都要返回新的Promise物件

所以只需要把then方法修改一下。

這部分可能會迷惑,但是我想先說一下這裡做了哪些事情,其實變化不大

之前的then做了哪些事情?

  • 就是依照不同的state,呼叫了successFn或errorFn,如果是pendding狀態就先緩存起來,等將來resolve時呼叫

鍊式then有哪些改動?

  • 首先then有了回傳值,回傳一個promise,而之前沒有回傳值,return的是undefined

  • new Promise的過程,其實邏輯沒什麼變化,唯一注意的,例如狀態fulfilled時,並非直接呼叫successFn

#而是呼叫_successFn,​​而這個函數內部本質上還是呼叫successFn(),但同時把呼叫的回傳值當作了resolve的參數,呼叫了resolve()

#因為當successFn被調用,得到返回值時,就表示這個函數執行完了,

就需要執行下一個非同步函數了,這樣下一個非同步函數也會把successFn(res)的return值當作參數

       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 )
                    }
                } )

            }

以上是Promise實現想法的深入分析(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除