先端面接の手書きPromise


前言
最近は前端面接でプロミスを手書きで依頼されていますが、プロミスは解決の前端にあるリピーター地獄の案として広く使われています.nodejsはさらにプロモーションインターフェースに戻るため、面接からも実際の仕事からもプロミススに慣れています.
分析プログラム
一つの機能を実現するには、まず何が必要かを知り、Promiseを実現するのも同じです.
では、Promiseはどのような機能を提供していますか?まずPromiseでよく使われている方法を列挙します.
//   Promise      new Promise(),  Promise    

class Promise {
    /**
     *     Promise.resolve(something).then(...)
     *   Promise.resolve      Promise  
     **/
    static resolve() {}
    
    //   
    static reject() {}
    
    /**
     *               
     *       resolve,reject    ,      
     * Promise  fn  resolve/reject   
     */
    constructor(fn) {}
    
    /**
     *   constructor      Promise        
     * pending,fullfilled,rejected
     *              promise     
     */
    _status = 'pending' // promise      pending
    
    /**
     *           promise     
     *    new Promise((resolve) => resolve(2));
     **/
     _result
    
    /**
     *     resolve      
     *   resolve  promise                
     **/
    resolve(ret) {}
    
    //   
    reject(ret) {}
    
    /**
     * then    promise     ,  then    ,      
     * then       , promise                
     *      then            。
     *       then       
     * const promise = new Promise(fn)
     * promise.then(fn1)
     * promise.then(fn2)
     *   then        , promise.then(fn3).then(fn4)
     *     then       promise  
     **/
    then(fn, fn2) {}
    
    //    then ,                   then     
    _successCallback = []
    _errorCallback = []
    
    //                       
    //     type    successCallback  errorCallback
    _runCallbackAsync(type) {}
}
実現する
Promiseの核心機能を分析してから、順次これらのインターフェースを実現します.
//             ,        
class Promise {
    ...
    constructor(fn) {
        //                    fn
        //  fn  try catch   ,  fn    
        try {
            //new Promise((resolve, reject) => {})
            fn(this.resolve.bind(this), this.reject.bind(this))
        } catch(e) {
            this.reject(e)
        }
    }
    
    // resolve       promise   ,      callback
    resolve(result) {
        // promise     pending,   promise     reject/resolve
        if(this._status !== 'pending') throw new Error('    promise')
        //       
        this._result = result
        //     callback
        this._runCallbackAsync('success')
    }
    
    // reject    
    reject(err) {
        if(this._status !== 'pending') throw new Error('    promise')
        this._result = err
        //           
        this._runCallbackAsync('error')
    }
    
    ...
}
promise.thenを書く前に、この方法は何をしているのかを改めて考えてみます.私たちは徐々にこの機能点を実現します.
  • thenは2つの関数を受信して、私達はとりあえずそれを成功コールとエラーコールと呼び、それぞれフルフィルドとrejecedの時に
  • を実行します.
  • promise状態が既に決議状態である場合、対応する成功コール/エラーコールを直ちに実行する
  • .
  • は新たなプロモーションに戻り、新たなプロモーションが成功しました.
    class Promise {
        ...
        //       
        
        then(fn1, fn2) {
            //       ,        promise  
            return new Promise((resolve, reject) => {
                /**                    ,      promise
                  *     _runCallbackAsync  。
                  *                      promise 
                  *                   
                  */
                
                //       
                const successCallBack = (result) => {
                    try {
                        //  promise               ,              promise     
                        resolve(fn1(result))
                    } catch(e) {
                        //       ,          promise
                        reject(e)
                    }
                }
                
                const errorCallback = (e) => {
                    try {
                        reject(fn2(e))
                    } catch(err) {
                        reject(err)
                    }
                }
                
                //            
                if (fn1 && this._status !== 'error') this._successCallback.push(fn1)
                if (fn2 && this._status !== 'success') this._errorCallback.push(fn2)
                
                //   promise    ,          
                if(this._status === 'success') this._runCallbackAsync('success')
                if(this._status === 'error') this._runCallbackAsync('error')
            })
        }
        
        //   
        _runCallbackAsync(type) {
            let eventQueue;
            if(type === 'error') eventQueue = this._errorCallback;
            else eventQueue = this._successCallback;
            //     ,   settimeout      
            setTimeout(() => {
                eventQueue.forEach(callback => callback(this._result));
                //       ,           ,  promise         ,             ,       
                this._errorCallback.length = 0;
                this._successCallback.length = 0;
            }, 0)
        }
        ...
    }
    このPromiseの核心方法はすでに実現しました.残りの方法は既存の方法を使って実現しやすいです.
    class Promise {
        ···
        catch(fn) {
            return this.then(undefined, fn);
        }
        
        static resolve(any) {
            //          any   
            if (
                typeof any.then === 'function'
                typeof any.catch === 'function'
                ...
            ) return any;
            //       promise       promise
            return new Promise((resolve) => {
                resolve(any)
            })
        }
        ···
    }
    締め括りをつける
    したがって、promiseを実現するポイントは、promiseを理解して一回だけ決定し、三つの状態があります.then/catchはチェーンコールをサポートします.そして、then/catchの本質はイベント登録器です.then=subscribeに似ています.
    最後の最後:技術文章を書き始めたばかりです.もし間違いがあったら、指摘してください.いいと思ったら、ほめてください.ありがとうございます.
    最後にソースリンクを添付します.https://github.com/MinuteWong...