天天看點

手寫Promise前言什麼是Promise A+ 規範promise類的設計實作Promise 三種狀态如何實作 resolve如何實作 reject如何實作 then總結

前言

如果想實作一個Promise 需要從以下幾個方面考慮

  • 符合 promise A+規範
  • Promise類的設計
  • 狀态設計(pending/fulfilled/reject)
  • 如何實作 resolve
  • 如何實作 reject
  • 如何實作 then

什麼是Promise A+ 規範

promisesaplus

  1. “promise” is an object or function with a

    then

    method whose behavior conforms to this specification.
  2. “thenable” is an object or function that defines a

    then

    method.
  3. “value” is any legal JavaScript value (including

    undefined

    , a thenable, or a promise).
  4. “exception” is a value that is thrown using the

    throw

    statement.
  5. “reason” is a value that indicates why a promise was rejected.
  6. A promise must be in one of three states: pending, fulfilled, or rejected.

promise類的設計

我們在使用 Promise的時候,都是通過 new 關鍵字調用, 是以借助 ES6 class 實作 Promise的聲明
class DDFPromise {
  constructor(executor) {
    executor(executor);
  }

複制代碼           

複制

實作Promise 三種狀态

我們在使用Promise時,注意到,Promise有三種狀态 fulfill/reject/pending
  • new Promise(()=> {}) 此時的狀态為pending
  • new Promise(()=> {}).then() 此時的狀态為fulfill
  • new Promise(()=> {}).catch() 此時的狀态為reject
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
    constructor(executor) {
        this.status = PENDING_STATUS;
        executor(executor);
     }
}

new DDFPromise(() => {
  console.log("代碼執行");
});
複制代碼           

複制

如何實作 resolve

實作resolve 需要關注兩個點
  • 狀态
  • 傳回值
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
    constructor(executor) {
      this.status = PENDING_STATUS;
      this.value = null;
      const resolve = (value) => {
        if (this.status === PENDING_STATUS) {
          this.status = FULFILL_STATUS;
          console.log("resolve被執行", value);
**          **this.value = value
       }
     };
      executor(resolve);
     }
}

new DDFPromise((resolve) => resolve("resolve傳入的參數"))
複制代碼           

複制

如何實作 reject

實作resolve 需要關注兩個點
  • 狀态
  • 傳回值
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
    constructor(executor) {
      this.status = PENDING_STATUS;
      this.value = null;
      const resolve = (value) => {
        if (this.status === PENDING_STATUS) {
          this.status = FULFILL_STATUS;
          console.log("resolve被執行", value);
          this.value = value
       }
     };
      const reject = (reason) => {
        if (this.status === PENDING_STATUS) {
          this.status = REJECT_STATUS;
          this.reason = reason;
       }
     };
      executor(resolve, reject);
     }
}

new DDFPromise((resolve, reject) => {
  resolve("resolve傳入的參數");
  reject("reject傳入的參數");
})
複制代碼           

複制

如何實作 then

實作then 需要關注 以下幾點
  • then方法的兩個入參
  • then方法的兩個入參 如何與constructor中定義的resolve/reject做關聯
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
  constructor(executor) {
    this.status = PENDING_STATUS;
    this.value = null;
    this.reason = null;
    const resolve = (value) => {
      if (this.status === PENDING_STATUS) {
        this.status = FULFILL_STATUS;
        this.value = value;
        this.onfulfilled(this.value);
      }
    };
    const reject = (reason) => {
      if (this.status === PENDING_STATUS) {
        this.status = REJECT_STATUS;
        this.reason = reason;
        this.onrejected(this.reason);
      }
    };
    executor(resolve, reject);
  }
  
  then(onfulfilled, onrejected) {
    this.onfulfilled = onfulfilled;
    this.onrejected = onrejected;
  }
}

const ddfPro = new DDFPromise((resolve, reject) => {
    resolve("resolve傳入的參數");
    // reject("reject傳入的參數");
});

ddfPro.then(
    (res) => {
      console.log("fulfilled", res);
    },
    (err) => {
      console.log("reject", err);
    }
);
複制代碼           

複制

上邊代碼執行時報錯 this.onfulfilled is not a function,報錯的原因:new Prose(()=>{}) 入參的代碼會立刻執行,而執行時this.onrejected,還沒有聲明,其實我們可以借助 Event Loop 解決此問題

解決then方法聲明 調用時報錯

queueMicrotask | setTimeout
const PENDING_STATUS = "pending";
const FULFILL_STATUS = "fulfill";
const REJECT_STATUS = "reject";
class DDFPromise {
  constructor(executor) {
    this.status = PENDING_STATUS;
    this.value = null;
    this.reason = null;
    const resolve = (value) => {
      if (this.status === PENDING_STATUS) {
        this.status = FULFILL_STATUS;
        queueMicrotask(() => {
          this.value = value;
          this.onfulfilled(this.value);
        });
     }
  };
  const reject = (reason) => {
    if (this.status === PENDING_STATUS) {
       this.status = REJECT_STATUS;
       queueMicrotask(() => {
         this.reason = reason;
         this.onrejected(this.reason);
       });
      }
    };
    executor(resolve, reject);
  }
  then(onfulfilled, onrejected) {
    this.onfulfilled = onfulfilled;
    this.onrejected = onrejected;
  }
}

const ddfPro = new DDFPromise((resolve, reject) => {
// resolve("resolve傳入的參數");

// reject("reject傳入的參數");
});

ddfPro.then(
  (res) => {
     console.log("fulfilled", res);
  },
  (err) => {
    console.log("reject", err);
  }
);
複制代碼           

複制

總結

經過如上步驟,隻完成了Promise的基本操作,