iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 23
1
Modern Web

從0開始的網頁生活!30天從網頁新手到網頁入門系列 第 23

Day23-非同步實作篇 II!Promise

本文已搬家到筆者自己的部落格嘍,有興趣的可以點這個連結

前言

昨天的文章介紹了 $.ajax() 這個用來進行 AJAXAPI ,但 $.ajax() 其實有蠻多瓶頸的並不是每種 非同步 的狀況都適用,舉例來說:我今天有三個 API 要同時發送待全部都回傳成功後再一併顯示,這種情況用 $.ajax() 就比較難處理,所以筆者今天就是要來介紹另一種用來處理 非同步 的方法: Promise

Promise演進

在前面的文章有提到,其實 Promise 是在 ES6 的時候才正式被 JavaScript 納入為基本 API ,可是 ES6 是在2015年才發表,在2015年之前的工程師又是如何利用 Promise 來處理比較複雜的 非同步 呢?

其實 Promise 有一個規範標準叫:Promise/A+,之後在2013年的時候有一位大大發明了bluebirdbluebird 實現了 Promise/A+ 的標準,大家不妨可以點擊那個超連結去看一下裡面的 API ,可以發現 bluebirdAPI 跟現在的 ES6 Promise 操作方法幾乎一模一樣, ES6 Promise 可是說是 bluebird 改良版阿!於是現在比較少人再用 bluebird 都直接寫 Promise 了, JavaScript 真是英明阿!

Promise初始化

在開始介紹一些基本操作之前先來講講兩種初始化 Promise 物件的方法吧!

  • new Promise

    // 初始化一個新的Promise物件
    let promise = new Promise((resolve, reject) => {
      // if success -> resolve data
      resolve(data)
      // if error -> reject error
      reject(err)
    })
    

    我們可以發現在 new Promise() 的括號裡面要寫一個 callback function ,而這個 callback function 有兩個參數一個是 resolve 另一個是 reject 這兩個代表什麼呢?

    • resolve()

      resolve 代表操作成功,並將括號內的值回傳回去。

    • reject()

      reject 代表操作失敗,並結束操作。

讓我們把上面提到的 resolve() 以及 reject() 做個結合吧!

  • Promise.resolve() / Promise.reject()

    其實這兩種寫法就是 new Promise() 的簡寫。

    // 省略 new Promise的過程,直接 resolve(1)
    let promise = Promise.resolve(1)
    // 正常寫法
    let promise = new Promise((resolve, reject) => {
      resolve(1)
    })
    

Promise狀態與流程

一般來說 Promise 的流程會長成底下這張圖。

大家有沒有發現在上圖中有 fulfill 以及 reject 這兩個路線,其實這個代表的是 Promise 的狀態。

  • fulfill

    代表操作成功所以對應到 resolve()

  • reject

    代表操作失敗所以對應到 reject()

Promise基本操作

在講完基本觀念與流程之後接下來講點 Promise 的基本操作吧! Promise 的基本操作就跟程式的 trycatch 很像。

  • .then()

    Promise 狀態為 fulfill 時,就可以用 Promise.then() 來操作 resolve() 的回傳值。

  • .catch()

    Promise 狀態為 reject 時,就可以用 Promise.catch() 來操作 reject() 的錯誤值。

    溫馨小提醒:不管是 Promise.then() 還是 Promise.catch() 都會回傳 Promise 物件喔!而且 Promise.then() 以及 Promise.catch() 括號內都要寫 callback funciton 喔!

Promise進階操作

講完基礎操作接下來講點進階操作吧!還記得前言提到的一次發送多個請求待全部請求都完成後再一併處理,這種時候就必須要用到 Promise 一些比較進階的操作啦!

  • Promise.all()

    Promise.all() 可以想成是一個一個 Promise 的集合,所以操作方法也跟一般的 Promise 一樣,最主要的功能就是等到括號內所有的 Promise 其狀態都是 fulfill 後才會開始執行,回傳值也會是個 Promise 物件,而 Promise.all() 的寫法如下。

    let p1 = Promise.resolve(3)
    let p2 = 1337
    let p3 = new Promise((resolve, reject) => {
      setTimeout(resolve, 100, 'foo')
    })
    
    Promise.all([p1, p2, p3]).then(values => { 
      console.log(values)  // [3, 1337, "foo"] 
    })
    

Promise的優點

講了這麼多 Promise 的操作,接著來提一下在昨天提到的 callback hell 問題吧!

Promise 自所以可以有效防止 callback hell 的發生就是來自 Promise.then() ,透過 Promise.then() 可以有效的串接一連串具有 關聯性AJAX ,就像下圖這樣。

所以未來要發生 callback hell 的機率幾乎等於0了,感謝 Promise 讚嘆 Promise XD

axios

axios 是個以 Promise 為主用來進行前後端溝通的好用 API ,既然是用來進行前後端溝通,想必又跟昨天介紹的 http method 有關聯了,沒錯!其實 axios 就是利用 http method 來進行前後端溝通,而 axios 厲害的地方就在於他會將後端回傳的資料包裝成 Promise 物件給前端操作,所以之後可以利用 Promise.then() 以及 Promise.catch() 來操作回傳的資料非常方便。

在開始使用 axios 之前要記得先在 codepenJavaScript 設定上面先引用 axios 喔!

Imgur

axios 基本操作有以下幾種:

  • axios.get(url)

    發送 GET 的請求應用於從後端取得資料。

  • axios.post(url)

    發送 POST 的請求用於提交資料至後端。

  • axios.patch(url)

    發送 PATCH 的請求用於套用資料至後端修改。

  • axios.delete(url)

    發送 DELETE 的請求用於刪除後端指定資料。

總結

今天介紹了 Promise 這個用來處理 非同步 相當好用的物件,也介紹了 axios 這個 promise baseAPIPromise 可以說是 非同步 必會的一種方法,大家以後如果要寫任何的前後端溝通不妨可以試試看筆者提供的方法來操作,而今天的小練習就只是把昨天的 $.ajax() 稍微改成 axios 提供給讀者們參考, 非同步實作 到這邊就告一個段落了,這算是一個蠻不好理解的觀念,如果讀者有任何問題都歡迎在底下留言給我,我都會一一解答喔!


上一篇
Day22-非同步實作篇 I!$.ajax()
下一篇
Day24-閉包!closure
系列文
從0開始的網頁生活!30天從網頁新手到網頁入門30

尚未有邦友留言

立即登入留言