Day30 | JS 的 axios 套件與 HTTP 狀態碼
❒ 甚麼是 AJAX
AJAX 是「 Asynchronous JavaScript and XML 」( 非同步的 JavaScript 與 XML 技術 )的縮寫,簡單說就是網頁不用重新整理,就能即時地透過瀏覽器去跟伺服器溝通,撈出資料。
使用者在不換頁的情況下,還是擁有很好的使用者體驗,點選其他頁面只更新局部資料,不須每次都等網頁整理完載入其他周邊資訊,才可以看到想要的資料。
點選其他頁面,不須等整個頁面重新載入,只會重新載入有變更的區域。
❒ 什麼是網路請求?
在網頁上 ( 例如 chrome ) 輸入網址,按下 Enter 這個動作等同於我傳送了一個網路請求。
我透過 chrome 發出一個網路請求,此請求為想要取得 ( get ) 一個網頁上的資訊。
要 get 一個網址,就會幫你找這個網址有沒有對應的伺服器,有的話就會連到對應的伺服器 ( 網址頁面 ) 去。
從網頁架構瞭解網頁請求
- 可從 chrome 開發者工具的 Network 查詢裡面有幾個網路請求。剛開始開啟 Network 裡面沒資料,可按重新整理。
- 以目前檔案內有 index.html 與 all.js ,載入的先後順序為 index.html 載入完會開始由上至下逐行解析 html 裡面的結構,最後顯示在網頁上。
Network 可見有三個網路請求 → index.html 、圖片、all.js。 這些網路請求是有先後順序如下圖,非一次一起出現。
❒ 關於 request 請求、response 回傳
request 請求
在傳送資料時,不是只 get 傳送一個網址伺服器就會回傳資料,會有一連串驗證,驗證資料沒問題,伺服器才會回傳資料給瀏覽器。
- Request Headers 使用者是看不到的,裡面的資訊主要是讓對方伺服器知道自己是甚麼身分 ( 表明 request 是誰、要傳送甚麼資料給對方伺服器、是甚麼瀏覽器 ),類似 html 中
<head></head>
內的資料 。
- 想透過網頁請求發一些資訊給伺服器,告知我要登陸了並給予帳號密碼,伺服器驗證後覺得可行,再回傳資料給網頁。
response 回傳
- 發 request 與網址給伺服器,伺服器驗證覺得沒問題 → 伺服器透過 response 把資料回傳到網頁。
- response 回傳的內容有 :
- Response Headers : 它不會顯示在網頁上,只是讓瀏覽器知道 Response Headers 有甚麼內容。Response Headers / Content-Type 可看到資料是甚麼格式 。
- Response Data : 實際真正回傳的字串內容。( Network / 左方點選檔案 / 右方點選 Response )
- Response Headers : 它不會顯示在網頁上,只是讓瀏覽器知道 Response Headers 有甚麼內容。Response Headers / Content-Type 可看到資料是甚麼格式 。
為什麼 Response Data 回傳的是字串內容,我們卻看的到網頁畫面的呈現 ?
Response Data 回傳的字串內容 ( Network / Response ),把它解析為 Content-Type 內的網頁格式 ( Network / Headers → Content-Type : text/html ),此時它就會用網頁格式做渲染讓我們看到畫面呈現。
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 | // ------- axios 結構 |
範例 1. 使用 axios 讀取網址內的 JSON 資料
API 網址:https://hexschool.github.io/ajaxHomework/data.json
1 | axios.get('https://hexschool.github.io/ajaxHomework/data.json') |
撈取 API 網址成功後回傳
then
中的response
資料,response
下的data
內可見王小名
資訊。
試試故意把 URL 刪掉一個字讓網址錯誤,就會回傳
catch
中的err
錯誤資訊。
範例 2. 使用 axios 讀取網址內的 JSON 資料,渲染在網頁上
API 網址 : https://hexschool.github.io/ajaxHomework/data.json
❒ 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()
)。
步驟解析 :
- 宣告一個變數 ary 為空陣列。
- 使用
get
發出一個網路請求給伺服器,伺服器還在審核資料未回傳時,then
的函式是不會被觸發的 ( 會被丟到一個暫存區,等到伺服器跑好才會被執行 ) → 繼續往下跑去註冊randerData()
函式到 chrome 的 JS 裡面 ( 這時伺服器還再跑未回傳 ) → 繼續往下執行 line 18console.log(ary);
為空陣列 ( 印出 )。
這時還有個待處理的狀態 line 6 ~ line11,等到伺服器跑好了回傳 response,line 6 ~ line11 的函式就會開始執行,並且把伺服器回傳的 response 結果帶到 line7 的參數 response 上。開始往下執行剛剛待處理的狀態 :- line8 → 印出 資料回傳了
- line9 → arr 資料寫到 line4 空陣列中。
- line10 → 執行
randerData() ;
→ 跑 line13 印出變數ary
內的資料。 - line15 ~ line16 → 前方資料處理完後,把文字顯示在 html 上。
- 總結 :
在非同步執行後 ( line6 ),寫一個函式 ( line10 ) 去執行後續,但在這之前需先管理資料狀態ary=response.data;
( line9 ) 把資料狀態賦予回去外層變數let ary =[];
空陣列中。
以上可確保值都有吃到,再進行後續行為。
使用函式處理上方範例 2. 的程式碼:使用 axios 讀取網址內的 JSON 資料,渲染在網頁上
API 網址 : https://hexschool.github.io/ajaxHomework/data.json
❒ HTTP 狀態碼
HTTP 狀態碼可以讓我們了解 HTTP 請求是否已經被完成或是出了什麼問題,下方整理了 AJAX 較常使用到的狀態碼訊息:
- 成功回應 ( Successful responses, 200 ~ 299 )
- 200 OK:請求成功。
- 這區間的狀態碼表示伺服器有成功接收到用戶端要求。以 AJAX 的串接為例,如果回傳的 status 為 200,則代表有成功接收到資料。
- 重定向 300 ~ 399
- 304 Not Modified :已經有載入過,不會在跟伺服器要資料,會使用暫存的檔案。
- 用戶端錯誤 ( Client errors, 400 ~ 499 ) 這區間的狀態碼表示有錯誤發生,且錯誤來自於「用戶端」。以 AJAX 的串接為例,
- 回傳的 status 為 400,表示遠端伺服器接收到無效語法、無法理解請求,因此需要檢查程式碼有無寫錯的地方。
- 回傳的 status 為 403, 表示禁止使用,這代表用戶端沒有訪問權限,因此沒辦法成功串接資料。
- 回傳的 status 404,伺服器找不到請求的資源 ( 找不到檔案 ) 。
- 伺服器端錯誤 ( Server errors, 500 ~ 599 ) 如果發生狀態碼為 5xx 的錯誤,則表示錯誤發生跟「遠端伺服器」有關,此時就需要跟後端工程師進行協調了。
- 500 Internal Server Error :伺服器端發生未知或無法處理的錯誤 ( 接後端資訊時,可能會遇到 )。
參考資訊
- 六角學院
- MDN - HTTP 狀態碼