三步完成A+規範Promise,平均一行代碼一句註釋(上)

前言

這篇文章系列是由我上培訓班課程的一個筆記整理後完成。promise

帶小白一步步完成一個A+規範Promise實現,由淺入深。markdown

內容解析很是詳細,儘可能把每一個點爲何這樣寫都註釋清楚,某些地方甚至略顯囉嗦了。異步

平均一行代碼一句註釋,拆分爲三個版本1.0,2.0,3.0,層層遞進,最終3.0版本將實現Pomise/A+規範。(1.0版本保證簡單易懂)函數

至於本文爲何分爲上中下三篇,是怕不少人和我同樣看見太長的文章先收藏,再吃灰。ui

因此,毫不是懶:)。(其實就是)this

myPromise 1.0 介紹

熟悉promise的讀者能夠直接看下一節源碼spa

myPromise 1.0版本將完成一個能處理同步狀態的promise(不考慮異步)。實現了promise的如下特性,不少平常使用的時候並無注意到,殊不知不覺在用了。code

1.promise構造函數接收一個executor函數,且該函數當即執行(即同步執行)同步

2.executor函數接收兩個promise內部提供的方法resolve方法reject方法用於供使用者調用,在合適的時候改變promise成合適的狀態源碼

let mypromise = new Promise((resolve,reject) => {
  //這個箭頭函數就是executor
})
複製代碼

3.executor函數內部執行異常時會被捕獲並執行reject

let mypromise = new Promise((resolve,reject) => {
  throw new Error('拋出異常')
  //至關於執行了reject,代碼出現錯誤同理,會被捕獲且將錯誤傳給reject並執行。
})
複製代碼

4.具有三個狀態(resolve成功,reject失敗,pending等待)和then方法(使用者用於傳入onFulfilled函數onRejected函數)

let mypromise = new Promise((resolve,reject) => {
  resolve('成功')
})
mypromise.then((data) => { //onFulfilled函數
  console.log('then resolve---',data);
},(err) => { //onRejected函數
  console.log('then reject---',err);
})
//注意:then中的使用者傳入的onFulfilled函數和使用者executor中使用的resolve都是成功時要調用的方法,能夠認爲resolve觸發onFulfilled。

//reject和onRejected同上
複製代碼

5.只有promise處於pending狀態時,內部的executor才能成功調用resolvereject並改變狀態。

let mypromise = new Promise((resolve,reject) => {
  resolve('成功')//resolve內部會改變狀態由pending變resolve
  resolve('成功2')//這三行執行已經沒有反應
  reject('失敗')
  throw new Error('拋出異常')
})
複製代碼

myPromise 1.0 源碼

知道特性以後就是開始實現了,不得不感嘆大佬們的智慧。

很少說,開始上代碼,話都在註釋裏。

// myPromise 1.0
const RESOLVED = 'RESOLVED'
const REJECTED = 'REJECTED'
const PENDING = 'PENDING'
console.log('my promise working');
class Promise {
  constructor(executor) {//new Promise時,當即調用構造函數constructor,接收用戶傳入的executor。
    this.status = PENDING;//默認等待態
    this.value = undefined;//用於成功時數據存儲,多是js值,undefined,promise三者之一
    this.reason = undefined;//用於失敗緣由儲存

    let resolve = (value) => {//這兩個函數不綁定到this上是由於,這兩個函數不屬於實例,由使用者傳入
      if(this.status === PENDING) {//只有等待態才能改變狀態並執行resolve函數,非等待態調用直接return
        this.status = RESOLVED//用戶調用resolve時第一步,狀態置爲'resolve'
        this.value = value//第二步,保存成功消息
      } 
    }

    let reject = (reason) => {//同上
      if(this.status === PENDING) {//狀態已是resove或reject的時候即便調用也不執行
        this.status = REJECTED
        this.reason = reason
      }
    }

    
    try {//在executor外包裹trycatch是爲了捕獲運行時的錯誤,以及throw new Error()這種非用戶主動調用reject時的狀況。
      executor(resolve,reject);//執行器就是executor用戶傳入的函數,該函數當即執行
      //並傳入兩個函數給執行器使用。
      //並約定,用戶認爲成功或者說想調用'成功'方法或者是想將狀態置爲成功時使用resolve,並傳入成功消息
      //反之調用reject,並傳入失敗緣由
    } catch (error) {//假設trycatch捕獲到錯誤,自動調用reject。
      reject(error)//也就是說,用戶主動調用reject和promise內executor運行出錯都會調用reject。
    }
    
  }


  //上面是promise調用時初始化執行的構造器,下面是promise這個類自帶的方法
  then(onFulfilled,onRejected) { //使用者調用promise的then方法,傳入成功時調用的函數,失敗時調用的函數
    if(this.status === RESOLVED) {//而後then執行,根據promise的狀態決定調用的函數
      onFulfilled(this.value);
    }
    if(this.status === REJECTED) {
      onRejected(this.reason)
    }
  }
}

module.exports = Promise

//也就是說,用戶調用promise,promise當即執行,並改變promise的狀態,當用戶調用then的時候
//傳入兩個狀態對應的要執行的方法。promise根據當前狀態的不一樣,選擇執行resolve或reject

複製代碼

立刻試試

let Promise = require('./promise') //引入本身的promise實驗一下

let mypromise = new Promise((resolve,reject) => {
  resolve('成功')//改變狀態由pending變resolve
  throw new Error('拋出異常')//後兩行執行已經沒有反應
  reject('失敗')
})
mypromise.then((data) => {
  console.log('then resolve---',data);
},(err) => {
  console.log('then reject---',err);
})
複製代碼

最後輸出:my promise working then resolve--- 成功

總結

若是能幫到你們就是對我最大的鼓勵,1.5和2.0代碼註釋版已經基本完成,寫好後會排markdown版發出。

下期,1.5版本做爲過渡,2.0版本將解決異步、鏈式調用的問題。

myPromise1.0其實很簡單的東西,可是也不排除有沒發現的錯誤,你們輕噴,感謝閱讀,感謝指錯。

相關文章
相關標籤/搜索