最最最通俗易懂的promise手寫系列(一)

JuoJuo發表於2018-07-25

先看一下這一次要講的涉及到的promise的基礎用法

let pms = new Promise((resolve, reject) => {
    setTimeout(() => {
        if (parseInt(Math.random()*10) > 5) {
             console.log('隨機數大於5,算任務成功了')
             resolve('還可以傳參哦')
        } else {
            console.log('隨機數< 5,算任務失敗了')
            reject('還可以傳參哦< 5')
        }
    }, 1500)
  })

  pms.then((value) => {
    console.log('success', value)
  }, (reason) => {
    console.log('fail', reason)
  })
複製程式碼

1.5s後如果隨機的數大於5走resolve()輸出:
'隨機數大於5,算任務成功了', 'success',
小於5走reject(),輸出:
'隨機數< 5,算任務失敗了', 'fail'.

我們先寫promise的這兩個功能:

  1. 建構函式的引數接受一個函式。
  2. 函式在被呼叫的時候,會被promise傳入兩個引數resolve跟reject。
  function Promise(executor){
    executor(resolve, reject)
    function resolve(){}
    function reject(){}
  }
複製程式碼

可以看到一new Promise就會執行傳入的函式,也就是我們起名為executor的函式.

  1. 大家肯定納悶兒為啥要在executor裡呼叫resolve或者reject,我們裡先上程式碼:
  function Promise(executor) {
    let self = this;
    self.value = undefined;
    self.reason = undefined;
    self.status = 'pending';

    self.onFulFilledCallbacks = [];
    self.onRejectedCallbacks = [];

    function resolve(value) {
        if (self.status === 'pending') {
            self.value = value;
            self.status = 'resolved'

            self.onFulFilledCallbacks.forEach(onFulFilled => {
                onFulFilled()
            });
        }
    }
    function reject(reason) {
        if (self.status === 'pending') {
            self.reason = reason;
            self.status = 'rejected';
            self.onRejectedCallbacks.forEach(onRejected => {
                onRejected()
            });
        }
    }

    try {
        executor(resolve, reject);
    } catch (error) {
        reject(error)
    }
}

Promise.prototype.then = function (onFulFilled, onRejected) {
    if (this.status === 'pending') {
        this.onFulFilledCallbacks.push(() => {
            onFulFilled(this.value)
        }); 
        this.onRejectedCallbacks.push(() => {
            onRejected(this.reason)
        })
    } else if (this.status === 'resolved') {
        onFulFilled(this.value);
    } else if (this.status === 'rejected') {
        onRejected(this.reason);
    }
}
複製程式碼
  • promise的三種狀:等待pending,成功resolve,失敗rejected.(說直接一點就是用來記錄resolve或者reject是否已經呼叫,也就是常說的那個executor任務執行成功了還是失敗了)

  • 這一次我們新增了兩個陣列onFulFilledCallbacks、onRejectedCallbacks用來儲存呼叫then的時候傳的兩個回撥函式(當然如果在呼叫then的時候已經resolve或reject,那就直接執行傳入的函式,不用儲存了),所以executor裡一定會呼叫resolve或者reject中的一個,因為一個函式的執行不是(邏輯上成功)就是(邏輯上失敗).對應我們寫的例子就是隨機數不是大於5就是小於5.

  • executor任務成功了肯定有成功後的結果,失敗了我們肯定也拿到失敗的原因。所以value與reason一個是用來儲存成功的結果,一個是用來儲存失敗的原因。

  • ps:onFulFilledCallbacks、onRejectedCallbacks定為陣列的原因是為了這個功能:

pms.then((value) => {
    console.log('success1', value)
  }, (reason) => {
    console.log('fail1', reason)
  })
pms.then((value) => {
    console.log('success2', value)
  }, (reason) => {
    console.log('fail2', reason)
  })
//then多次得把這些函式給存起來,到時候成功或者失敗的時候,遍歷依次執行~
複製程式碼

下一張我們進入Promise最迷人的鏈式呼叫.
最最最通俗易懂的promise手寫系列(二)- 鏈式呼叫

相關文章