promise

zlppassion發表於2020-04-22

Promise深入 + 自定義Promise

1. 準備

1.1. 函式物件與例項物件

1. 函式物件: 將函式作為物件使用時, 簡稱為函式物件
2. 例項物件: new 函式產生的物件, 簡稱為物件

1.2. 回撥函式的分類

1. 同步回撥: 
    理解: 立即執行, 完全執行完了才結束, 不會放入回撥佇列中
    例子: 陣列遍歷相關的回撥函式 / Promise的excutor函式
2. 非同步回撥: 
    理解: 不會立即執行, 會放入回撥佇列中將來執行
    例子: 定時器回撥 / ajax回撥 / Promise的成功|失敗的回撥
 // 1. 同步回撥函式
    // const arr = [1, 3, 5]
    arr.forEach(item => { // 遍歷回撥, 同步回撥函式, 不會放入列隊, 一上來就要執行完
      console.log(item)
    })
    console.log('forEach()之後')

    // 2. 非同步回撥函式
    setTimeout(() => { // 非同步回撥函式, 會放入佇列中將來執行
      console.log('timout callback()')
    }, 0)
    console.log('setTimeout()之後')

1.3. JS中的Error

1. 錯誤的型別
    Error: 所有錯誤的父型別
    ReferenceError: 引用的變數不存在
    TypeError: 資料型別不正確的錯誤
    RangeError: 資料值不在其所允許的範圍內
    SyntaxError: 語法錯誤
2. 錯誤處理
    捕獲錯誤: try ... catch
    丟擲錯誤: throw error
3. 錯誤物件
    message屬性: 錯誤相關資訊
    stack屬性: 函式呼叫棧記錄資訊

2. Promise的理解和使用

2.1. Promise是什麼?

1.抽象表達: 
    Promise是JS中進行非同步程式設計的新的解決方案(舊的是誰?)
2.具體表達:
    從語法上來說: Promise是一個建構函式
    從功能上來說: promise物件用來封裝一個非同步操作並可以獲取其結果
3. promise的狀態改變(只有2種, 只能改變一次)
    pending變為resolved
    pending變為rejected
4. promise的基本流程

promise基本流程

2.2. 為什麼要用Promise?

1. 指定回撥函式的方式更加靈活: 可以在請求發出甚至結束後指定回撥函式
2. 支援鏈式呼叫, 可以解決回撥地獄問題
3. 1. 指定回撥函式的方式更加靈活: 
    舊的: 必須在啟動非同步任務前指定
    promise: 啟動非同步任務 => 返回promie物件 => 給promise物件繫結回撥函式(甚至可以在非同步任務結束後指定)

  2. 支援鏈式呼叫, 可以解決回撥地獄問題
    什麼是回撥地獄? 回撥函式巢狀呼叫, 外部回撥函式非同步執行的結果是巢狀的回撥函式執行的條件
    回撥地獄的缺點?  不便於閱讀 / 不便於異常處理
    解決方案? promise鏈式呼叫
    終極解決方案? async/await

2.3. 如何使用Promise?

1. 主要API
    Promise建構函式: Promise (excutor) {}
    Promise.prototype.then方法: (onResolved, onRejected) => {}
    Promise.prototype.catch方法: (onRejected) => {}
    Promise.resolve方法: (value) => {}
    Promise.reject方法: (reason) => {}
    Promise.all方法: (promises) => {}
    Promise.race方法: (promises) => {}
2. 幾個重要問題
    如何改變promise的狀態?
    一個promise指定多個成功/失敗回撥函式, 都會呼叫嗎?
    promise.then()返回的新promise的結果狀態由什麼決定?
    改變promise狀態和指定回撥函式誰先誰後?
    promise如何串連多個操作任務?
    promise異常傳(穿)透?
    中斷promise鏈

3. 自定義Promise

1. 定義整體結構
2. Promise建構函式的實現
3. promise.then()/catch()的實現
4. Promise.resolve()/reject()的實現
5. Promise.all/race()的實現
6. Promise.resolveDelay()/rejectDelay()的實現
7. ES6 class版本

4. async與await

1. async 函式
    函式的返回值為promise物件
    promise物件的結果由async函式執行的返回值決定

2. await 表示式
    await右側的表示式一般為promise物件, 但也可以是其它的值
    如果表示式是promise物件, await返回的是promise成功的值
    如果表示式是其它值, 直接將此值作為await的返回值

3. 注意:
    await必須寫在async函式中, 但async函式中可以沒有await
    如果await的promise失敗了, 就會丟擲異常, 需要通過try...catch來捕獲處理

5. JS非同步之巨集佇列與微佇列

巨集佇列與微佇列

1. 巨集列隊: 用來儲存待執行的巨集任務(回撥), 比如: 定時器回撥/DOM事件回撥/ajax回撥
2. 微列隊: 用來儲存待執行的微任務(回撥), 比如: promise的回撥/MutationObserver的回撥
3. JS執行時會區別這2個佇列
	JS引擎首先必須先執行所有的初始化同步任務程式碼
	每次準備取出第一個巨集任務執行前, 都要將所有的微任務一個一個取出來執行

rver的回撥
3. JS執行時會區別這2個佇列
JS引擎首先必須先執行所有的初始化同步任務程式碼
每次準備取出第一個巨集任務執行前, 都要將所有的微任務一個一個取出來執行

相關文章