Day30 | JS 的 axios 套件與 HTTP 狀態碼

❒ 甚麼是 AJAX

AJAX 是「 Asynchronous JavaScript and XML 」( 非同步的 JavaScript 與 XML 技術 )的縮寫,簡單說就是網頁不用重新整理,就能即時地透過瀏覽器去跟伺服器溝通,撈出資料。

使用者在不換頁的情況下,還是擁有很好的使用者體驗,點選其他頁面只更新局部資料,不須每次都等網頁整理完載入其他周邊資訊,才可以看到想要的資料。

點選其他頁面,不須等整個頁面重新載入,只會重新載入有變更的區域。

❒ 什麼是網路請求?

在網頁上 ( 例如 chrome ) 輸入網址,按下 Enter 這個動作等同於我傳送了一個網路請求。
我透過 chrome 發出一個網路請求,此請求為想要取得 ( get ) 一個網頁上的資訊。
要 get 一個網址,就會幫你找這個網址有沒有對應的伺服器,有的話就會連到對應的伺服器 ( 網址頁面 ) 去。
利用網址按Enter 發出網路請求的過程

從網頁架構瞭解網頁請求

從網頁架構瞭解網頁請求

  • 可從 chrome 開發者工具的 Network 查詢裡面有幾個網路請求。剛開始開啟 Network 裡面沒資料,可按重新整理。
  • 以目前檔案內有 index.html 與 all.js ,載入的先後順序為 index.html 載入完會開始由上至下逐行解析 html 裡面的結構,最後顯示在網頁上。
    Network 可見有三個網路請求 → index.html 、圖片、all.js。 這些網路請求是有先後順序如下圖,非一次一起出現。
    chrome 開發者工具的 Network 截圖

❒ 關於 request 請求、response 回傳

request 請求

在傳送資料時,不是只 get 傳送一個網址伺服器就會回傳資料,會有一連串驗證,驗證資料沒問題,伺服器才會回傳資料給瀏覽器。

  • Request Headers 使用者是看不到的,裡面的資訊主要是讓對方伺服器知道自己是甚麼身分 ( 表明 request 是誰、要傳送甚麼資料給對方伺服器、是甚麼瀏覽器 ),類似 html 中 <head></head> 內的資料 。
    不論是 request ( 請求 ) 或是 response ( 回傳 ) 都會有 Headers 的資料
  • 想透過網頁請求發一些資訊給伺服器,告知我要登陸了並給予帳號密碼,伺服器驗證後覺得可行,再回傳資料給網頁。

response 回傳

  • 發 request 與網址給伺服器,伺服器驗證覺得沒問題 → 伺服器透過 response 把資料回傳到網頁。
  • response 回傳的內容有 :
    • Response Headers : 它不會顯示在網頁上,只是讓瀏覽器知道 Response Headers 有甚麼內容。Response Headers / Content-Type 可看到資料是甚麼格式 。
      ![截圖](https://ithelp.ithome.com.tw/upload/images/20221015/20119743eP6hPLFGPK.png)
      
    • Response Data : 實際真正回傳的字串內容。( Network / 左方點選檔案 / 右方點選 Response )

為什麼 Response Data 回傳的是字串內容,我們卻看的到網頁畫面的呈現 ?

Response Data 回傳的字串內容 ( Network / Response ),把它解析為 Content-Type 內的網頁格式 ( Network / Headers → Content-Type : text/html ),此時它就會用網頁格式做渲染讓我們看到畫面呈現。
Response 會回傳的資訊

request 請求 & response 回傳 | 統整

  • 不論是 request ( 請求 ) 或是 response ( 回傳 ) 都會有 Headers 的資料。
  • 透過瀏覽器或其他方式都可以發出網路請求給伺服器,伺服器回傳會使用 response ,回傳會有 Response Headers 與 Response 本身的資料內容 Response Data。
    Response Data 中的 data 會被編譯為檔案、HTML、圖片 .. 等其他格式,會從 Response Headers 的 Content-Type 得知而進行編譯。

❒ 各種發出網路請求的 JS 寫法種類

➊ JS 原生寫法

  • XMLHttpRequest : 最資深,每個網頁瀏覽器都有。

    1
    2
    3
    4
    5
    6
    7
    8
    // 結構
    function reqListener() {
    console.log(this.responseText);
    }
    var oReq = new XMLHttpRequest();
    oReq.addEventListener('load', reqListener);
    oReq.open('GET', 'http://example.org/example.text');
    oReq.send();
  • fetch : 較新的語法,在有些瀏覽器的運用上要留意是否有支援。

    1
    2
    3
    4
    5
    6
    7
    8
    // 結構
    fetch('http://example.com/movies.json')
    .then(function (response) {
    return response.json();
    })
    .then(function (myJson) {
    console.log(myJson);
    });

➋ 套件 axios ?

  • 需額外載入 JS。

  • 底層是使用 XMLHttpRequest 規則做出。

  • 精簡了 XMLHttpRequest 的程式碼,方便寫出簡潔的網路請求。

  • axios 寫法:

    • get('URL') 內的網址發出網路請求,成功後會跑 then 然後直行裡面的函式把資料回傳。

      1
      2
      3
      4
      5
      6
      7
      8
      // 結構
      axios.get('URL').then((response) => {
      console.log(response.data);
      console.log(response.status);
      console.log(response.statusText); // 狀態碼
      console.log(response.headers);
      console.log(response.config);
      })

❒ axios 套件

➊ 環境安裝

  • axios repository : https://github.com/axios/axios

  • 安裝方式 : axios 有多種安裝方式,可參考文件,本文章使用 CDN 方式。

    1
    2
    3
    4
    5
    <!-- 1.建議先載入套件的 js 檔案 ↓ -->
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

    <!-- 2.自己寫的 js 檔案 ↓ -->
    <script src="js/all.js"></script>

➋ 檢查是否有載入成功

方式一

開啟 chrome 開發者工具 / Network 可見 axios.min.js 與 all.js 的狀態 Status 皆為 200 → 如果顯示 404 表沒載入成功。

註: all.js 狀態碼 304 為已經有載入過,不會在跟伺服器要資料,會使用暫存的檔案。( 下方會有 HTTP 狀態碼解說 )
截圖

方式二

於自己的 js 檔案輸入 console.log(axios); ,會回傳 axios 的相關資料。
截圖

➌ 使用 axios 串接外部資料

1
2
3
4
5
6
7
8
9
10
11
12
13
// ------- axios 結構
// URL 可自行更換為想獲取資料的API網址
axios.get('URL')
.then((response) => {
// 成功回傳
console.log(response);
console.log(response.data); //為上方JSON格式的資料,統整 response物件中,於裡面撈出
console.log(response.status); // HTTP 狀態碼
})
.catch((err) => {
// 失敗回傳
console.log(err);
})

範例 1. 使用 axios 讀取網址內的 JSON 資料

API 網址:https://hexschool.github.io/ajaxHomework/data.json

1
2
3
4
5
6
7
axios.get('https://hexschool.github.io/ajaxHomework/data.json')
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
})
  • 撈取 API 網址成功後回傳 then 中的 response 資料,response 下的 data 內可見王小名資訊。
    截圖

  • 試試故意把 URL 刪掉一個字讓網址錯誤,就會回傳 catch 中的 err 錯誤資訊。
    截圖

範例 2. 使用 axios 讀取網址內的 JSON 資料,渲染在網頁上

API 網址 : https://hexschool.github.io/ajaxHomework/data.json

CodePen 範例

❒ axios 非同步觀念

截圖

  • 先印出 console.log(ary); → 空陣列,等待伺服器準備好資料回傳後就直接執行函式內的程式碼
  • 發網路請求給伺服器,等待伺服器回傳資料需要一些時間,還未等到資料回傳時 ( response 函式未執行,伺服器回傳資料後就會執行 response 的函式 ),程式碼就繼續往下運作,導致 console.log(ary); 會是空陣列。

為什麼不等到 axios 資料執行完再往下跑 console.log(ary); ?

如果 axios 內的資料很大,在等待下載的這段時間其他程式都不執行,網頁畫面會空白一片使用者體驗不好。所以都會先發出網路請求 get 再等待伺服器回傳資料的這段時間就繼續往下執行程式。
在繼續往下跑的這段時間,伺服器回傳資料後就會直接顯示出來。

如下,第一次 console.log(ary); 顯示空值 ( 伺服器還未回傳資料 ),第二次 console.log(ary); 就會顯示 resopnse 資料了 ( 伺服器回傳資料成功,執行 response 的函式 )。
截圖

透過函式設計處理非同步

截圖

  • 執行順序 : 3 → 1 → 2
  • 透過函式設計處理非同步可使用函式方式包裝,確保伺服器有正確回傳資料後,再執行函式,就有保障。
  • 東西都是被函式包裝起來,當資料寫入 ( 發出網路請求,伺服器回傳資料 ) 就可直接執行函式。
  • line10 renderData() 如果移至全域是不會得到 response.data 回傳的結果。

❒ 因 axios 非同步特性,建議透過函式處理非同步

截圖

  • 執行順序 : 3 → 1 → 2
  • 任何指令都先寫成一個函式,像是渲染畫面用的 renderData()。等伺服器回傳資料 response 後,觸發 then 的函式,再把資料 response 寫到 line4 空陣列中,再往下執行,也能確保資料有吃到 ( line 9 ) 再來做後續的行為 ( 渲染畫面 renderData() )。

步驟解析 :

  1. 宣告一個變數 ary 為空陣列。
  2. 使用 get 發出一個網路請求給伺服器,伺服器還在審核資料未回傳時, then 的函式是不會被觸發的 ( 會被丟到一個暫存區,等到伺服器跑好才會被執行 ) → 繼續往下跑去註冊 randerData() 函式到 chrome 的 JS 裡面 ( 這時伺服器還再跑未回傳 ) → 繼續往下執行 line 18 console.log(ary); 為空陣列 ( 印出 )。
    這時還有個待處理的狀態 line 6 ~ line11,等到伺服器跑好了回傳 response,line 6 ~ line11 的函式就會開始執行,並且把伺服器回傳的 response 結果帶到 line7 的參數 response 上。開始往下執行剛剛待處理的狀態 :
    • line8 → 印出 資料回傳了
    • line9 → arr 資料寫到 line4 空陣列中。
    • line10 → 執行 randerData() ; → 跑 line13 印出變數 ary 內的資料。
    • line15 ~ line16 → 前方資料處理完後,把文字顯示在 html 上。
  3. 總結 :
    在非同步執行後 ( line6 ),寫一個函式 ( line10 ) 去執行後續,但在這之前需先管理資料狀態 ary=response.data; ( line9 ) 把資料狀態賦予回去外層變數 let ary =[]; 空陣列中。
    以上可確保值都有吃到,再進行後續行為。

使用函式處理上方範例 2. 的程式碼:使用 axios 讀取網址內的 JSON 資料,渲染在網頁上

API 網址 : https://hexschool.github.io/ajaxHomework/data.json

CodePen 範例

❒ HTTP 狀態碼

HTTP 狀態碼可以讓我們了解 HTTP 請求是否已經被完成或是出了什麼問題,下方整理了 AJAX 較常使用到的狀態碼訊息:

  1. 成功回應 ( Successful responses, 200 ~ 299 )
    • 200 OK:請求成功。
    • 這區間的狀態碼表示伺服器有成功接收到用戶端要求。以 AJAX 的串接為例,如果回傳的 status 為 200,則代表有成功接收到資料。
  2. 重定向 300 ~ 399
    • 304 Not Modified :已經有載入過,不會在跟伺服器要資料,會使用暫存的檔案。
  3. 用戶端錯誤 ( Client errors, 400 ~ 499 ) 這區間的狀態碼表示有錯誤發生,且錯誤來自於「用戶端」。以 AJAX 的串接為例,
    • 回傳的 status 為 400,表示遠端伺服器接收到無效語法、無法理解請求,因此需要檢查程式碼有無寫錯的地方。
    • 回傳的 status 為 403, 表示禁止使用,這代表用戶端沒有訪問權限,因此沒辦法成功串接資料。
    • 回傳的 status 404,伺服器找不到請求的資源 ( 找不到檔案 ) 。
  4. 伺服器端錯誤 ( Server errors, 500 ~ 599 ) 如果發生狀態碼為 5xx 的錯誤,則表示錯誤發生跟「遠端伺服器」有關,此時就需要跟後端工程師進行協調了。
    • 500 Internal Server Error :伺服器端發生未知或無法處理的錯誤 ( 接後端資訊時,可能會遇到 )。

參考資訊