promise源碼分析

源碼取自:源碼博客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自己對象

相關文章
相關標籤/搜索