JavaScript 筆記 - AJAX
紀錄一下 AJAX 的相關知識。
AJAX 簡述
AJAX 是「Asynchronous JavaScript and XML」的縮寫,以名稱來看就是是非同步的 JavaScript 與 XML,可以讓 Web 前端與後端伺服器進行資料的交換,以及不需要重新載入網頁就能更新頁面內容。
過去 AJAX 發出請求會透過 XMLHttpRequest 物件來實作,但是以目前來說,因為有了更適合的方式,因此實務上幾乎不會使用 XMLHttpRequest,不過筆記都寫了,就稍微理解一下每個方法吧!(๑•̀ㅂ•́)و✧
XMLHttpRequest
建立 XHR 物件
1 | |
此時可以使用 readyState 屬性的回傳值來確認狀態。
1 | |
以下是不同回傳結果分別所代表的狀態意思:
0(UNSENT):成功建立一個 XMLHttpRequest 物件,但尚未使用open()連接伺服器。1(OPENED):已經使用open()連接伺服器,但尚未使用send()發送請求。2(HEADERS_RECEIVED):已使用send()發送請求,且可以取得 header 與狀態。3(LOADING):資料載入中。4(DONE):資料載入完成,成功接收所有數據。
open
1 | |
連接伺服器,參數依序分別為請求方法(get、post 等)、資料網址以及是否要非同步執行(預設為 true)。
setRequestHeader
1 | |
設定請求表頭,參數依序分別為表頭名稱與表頭值,以 post 請求來說,會用來設定發送主體的資料類型(Content-Type)。
另外,此方法一般會在發送 post 請求時呼叫(get 請求沒有發送主體因此不使用),程式碼位置會在 open() 之後以及 sned() 之前。
禁止設定的表頭欄位,請參閱 MDN - Forbidden header name
send
1 | |
發送請求,send() 的應用會根據請求方法的不同而有所差異,若只是單純的 get 請求,參數只需傳入 null 即可,其他請求方法如 post 則需補上相關資訊。
需要注意的是,資料發送前如果是 JSON 格式,則需要先轉型為字串,轉換型別的方法可以使用 JSON.stringify();同理,接收到的資料如果是字串,也可以透過 JSON.parse() 轉換為 JSON 物件。
相關資訊請參閱 MDN - XMLHttpRequest.send()
非同步執行
雖然可以選擇要以同步或是非同步方式來發出請求,但是為了避免網頁阻塞,一般都會透過非同步方式來執行,而非同步就會衍生出資料尚未載入完畢,程式碼就繼續往下執行的狀況,此時可以透過事件監聽來解決非同步問題。
針對 load 事件進行監聽:
1 | |
針對 xhr 物件進行 load 監聽,此時就能確保資料完全載入後,才執行指定操作,此外,可以發現資料的型別為字串,因此可以視情況將資料轉為物件或陣列使用。
字串轉為物件型別可參考 MDN JSON.parse()
HTTP 狀態碼
資料全部載入後,可以透過 status 屬性查看狀態碼。
1 | |
以下列出常見的狀態碼,以及代表意思:
- 200(請求成功)
- 404(用戶端錯誤)
- 500(伺服器端錯誤)
更多相關資訊可參考 MDN - HTTP 狀態碼
實作練習
使用六角學院練習 API 實作 get 請求:
1 | |
1 | |
使用六角學院練習 API 實作 post 請求(註冊功能):
資料類型:application/x-www-form-urlencoded
1 | |
資料類型:application/json
1 | |
jQuery AJAX
使用前需要引入 jQuery,此處使用 CDN 方式引入。
1 | |
起手式:
1 | |
以下為常用的參數:
url:請求資料的網址method:請求方法(get、post…)data:傳送的資料dataType:伺服器接收的資料格式(text、json…)contentType:傳送至伺服器的資料格式(預設為'application/x-www-form-urlencoded; charset=UTF-8')done:請求成功時的回傳結果fail:請求失敗時的回傳結果
若是沒有要向伺服器傳送資料(get 請求),則參數 data、contentType 可省略。
jQuery 3.0 版本開始,刪除了 success()、error() 以及 complete() 等方法,取而代之的是 done()、fail() 以及 always()。
相關內容請參閱官方文件說明。
實作練習
使用六角學院練習 API 實作 get 請求:
1 | |
1 | |
使用六角學院練習 API 實作 post 請求(註冊功能):
1 | |
Fetch
Fetch API 是 ES6 的原生方法,發出請求的方式相較 XHR 簡單了許多,此外 IE 瀏覽器不支援。
起手式:
1 | |
Fetch 方法接收兩個參數,第一個是請求資料的網址(必填),第二個參數是一個物件(選擇性使用),內容是 Request 的相關屬性設定,以下列出幾個常見的屬性:
method:請求方法(預設為get)headers:一個物件,內容為請求表頭相關資訊('Content-Type'…等,不設定則預設為{})body:傳送的資料(需要先轉為字串型別)
更多屬性設定請參閱 MDN - Fetch Request。
接著可以在程式碼下方看到 then() 的使用,而這也是 Fetch 獨特的地方,因為 Fetch 就是透過 Promise 來做回應,嘗試輸入以下程式碼進行測試:
1 | |

從印出的結果來看,可以確定 Fetch 會回傳一個狀態為 fulfilled(已實現)的 Promise 物件,並且在 response 當中也可以看到一些伺服器收到請求後回傳的資訊,而我們需要的資料就在 Response 的 body 屬性當中。
需要注意的是,第一次使用 then 接收 Promise 物件時,這裡的 body 屬性是一個 ReadableStream 物件,這意味著資料的內容無法直接讀取,因此在 return 給第二個 then 之前,需要先對 Response 進行特殊的處理,常見的做法像是先使用 json()、text() 轉型後再進行 return,這樣就能將實際的資料在下一個 then 進行進一步的操作。
詳細的 Response 處理方法請參閱 MDN - Using Fetch - body
另外對 Fetch 來說,只要伺服器有回傳 Response,無論狀態碼是 200、404 或是其他狀態,都會被 then 接收,若要查看較詳細的狀態,可以在 Fetch 回傳的 Response,也就是第一個 then 接收的結果中查看,而 catch 則是在請求資料網址不正確,或是網路連線異常的時候被執行。
實作練習
使用六角學院練習 API 實作 get 請求:
1 | |
使用六角學院練習 API 實作 post 請求(註冊功能):
1 | |
Axios
axios 是一個基於 Promise 的網路請求套件,作用於瀏覽器和 node.js。
axios 具備以下特點:
- 從瀏覽器發出 XMLHttpRequest
- 從 node.js 發出 http 請求
- 支援 Promise API
- 攔截請求和回應
- 轉換請求和回應資料
- 取消請求
- JSON 資料格式的自動轉換
使用前需要先引入 axios,以下使用 cdn 方式:
1 | |
axios 的使用方式相當簡單,開頭輸入 axios,接著再接上請求的方法即可,另外因為 axios 是基於 Promise,因此請求成功時,會回傳一個 Promise 物件,此時就會使用 then() 來做接收,而請求失敗時,就會透過 catch() 來取得錯誤的資訊。
以下直接使用六角學院練習 API 實作 get 請求並觀察回傳結果:
1 | |

從接收到的回傳物件中可以看到許多資訊,例如 config 屬性表示 axios 發出請求時預設的一些設定,常見的像是 method(請求方法)、headers(請求表頭)以及 url(請求的網址路徑)等等,另一個外層的 headers 屬性則是伺服器回應的相關資訊,而我們需要的資料就在 data 屬性裡面,除此之外,可以發現資料的格式已經被自動轉換為 JSON 物件了。
接著再來看 post 請求,照慣例一樣使用六角學院練習 API 實作 post 請求(註冊功能):
1 | |

發出 post 請求時,除了請求的資料網址之外,還需要加入第二個參數,也就是傳送給伺服器的資料。
axios API
可以使用以下兩種方式發出請求:
axios(config)
第一種方式是在物件中指定相關請求設定,並將物件傳入 axios 發出請求,以 POST 請求為例:
1 | |
axios(url[, config])
第二種方式是透過請求方法別名來發出請求,以下分別是 GET、POST 請求的範例:
1 | |
1 | |
以下列出官方文件提供的所有請求方法別名:
axios.request(config)axios.get(url[, config])axios.delete(url[, config])axios.head(url[, config])axios.options(url[, config])axios.post(url[, data[, config]])axios.put(url[, data[, config]])axios.patch(url[, data[, config]])
若沒有加上別名,預設會使用 get 來發出請求,另外在官方文件有提到使用別名方法時,不需要在 config(存放請求設定的物件)中指定 url、method 以及 data 屬性。
後記
關於 AJAX 筆記先暫時寫到這邊,後續如果時間充裕會再深入學習,並補充更多相關內容。