AJAX 全名為 Asynchronous JavaScript and XML(非同步 JavaScript 及 XML)
- AJAX 是一種用於創建快速動態網頁的技術。
- 在傳統的網頁(不使用 AJAX)如果需要更新內容,必須重載整個頁面。而AJAX 通過在後台與伺服器進行少量數據交換,使網頁實現異步更新。這意味著可以在不重載整個頁面的情況下,對網頁的某些部分進行更新。
XMLHttpRequest
Javascript
- 實例物件
const XHR = new XMLHttpRequest();
- 要送出一個 HTTP 請求,需要建立一個
XMLHttpRequest
物件、開啟一個 URL,並發起一個請求。
readyState will be 0
- 設定請求
XMLHttpRequest.open(method, url, async);
-
method
:要使用的HTTP方法,比如「GET」、「POST」、「PUT」、「DELETE」、等。url
:要向其發送請求的URL。async
:其取得資料的方式可以為非同步(asynchronously)或同步(synchronously)兩種之一。默認為true。- true:非同步 - 不等資料回傳,程式會繼續執行。
- false:同步 - 等資料回傳後,程式才會繼續執行。
readyState will be 1
- 請求表頭
XMLHttpRequest.setRequestHeader(header, value);
- 使用
post
時,需透過setRequestHeader()
方法,設置請求訊息的表頭欄位。
- 監聽事件
XMLHttpRequest.onload = callback;
- 使用非同步時,需監聽 load 事件,當
XMLHttpRequest
請求成功完成後執行相對應的函式 — 回調函式 (callback)。
- 發送請求
XMLHttpRequest.send()
- 用於發送 HTTP 請求。如果是非同步請求(默認為異步請求),則此方法會在請求發送後立即返回;如果是同步請求,則此方法直到響應到達後才會返回。
- 如請求使用 GET 方法,設為空值:
null
readyState will be 2
- 處理回應
- 回應的文字 text,可透過
responseText
屬性取得,
若 Server 回應的是 XML 或 XHTML,則使用responseXML
屬性,
若回應的是常見的 JSON,則可以使用JSON.parse()
方法,解析responseText
屬性。
readyState
Value | Status | Description |
---|---|---|
0 | UNSENT | XMLHttpRequest() 已被建立,但 open() 方法尚未被呼叫。 |
1 | OPENED | open() 方法已被呼叫,但未傳送任何資料。於此狀態時,可以使用 setRequestHeader() 方法設定請求標頭(request headers),並可呼叫 send() 方法來發送請求。 |
2 | HEADERS_RECEIVED | send() 方法已被呼叫,並且已接收到回應標頭(response header)。 |
3 | LOADING | 回應資料下載中,此時 responseText 會擁有部分資料。 |
4 | DONE | 請求操作已完成。這意味著資料傳輸可能已成功完成或是已失敗。 |
HTTP狀態碼
HTTP 狀態碼指的是從伺服器端回應(HTTP Response)的狀態,對於狀態的分類可區分三個層級,分別用三個數字表示,第一個數字為大類、第二個數字為中類、第三個數字為小類。
完整的狀態碼定義可以參考 10 Status Code Definitions 章節,裡面有完整且詳盡的說明。
XMLHttpRequest.status |
HTTP 狀態碼大致分成 5 類。
1xx - 參考資訊 (Informational)
這些狀態碼代表主機先暫時回應用戶端一個狀態,所以在接收一般的回應之前,用戶端應準備接收一個或多個 1xx 的回應。
2xx - 成功 (OK)
這類的狀態碼表示伺服器成功接收到用戶端要求、理解用戶端要求、以及接受用戶端要求。
3xx - 重新導向 (Redirection)
用戶端瀏覽器必須採取更多動作才能完成要求。例如:瀏覽器可能必須重新發出 HTTP Request 要求伺服器上的不同頁面。
4xx - 用戶端錯誤 (Client Error)
這代表錯誤發生,且這錯誤的發生的原因跟「用戶端」有關。例如:用戶端可能連結到不存在的頁面、用戶端的權限不足、或可能未提供有效的驗證資訊(輸入的帳號、密碼錯誤)。
5xx - 伺服器錯誤 (Server Error)
這代表錯誤發生,且這錯誤發生的原因跟「伺服器」有關。伺服器因為發生錯誤或例外狀況(Exception)而無法完成要求(Request)時,就會回應 5xx 的錯誤,且這肯定跟伺服器有關。
CORS
CORS - 跨來源資源共用(Cross-Origin Resource Sharing (CORS))是一種使用額外 HTTP 標頭令目前瀏覽網站的使用者代理取得存取其他來源(網域)伺服器特定資源權限的機制。
當使用者代理請求一個不是目前文件來源——例如來自於不同網域(domain)、通訊協定(protocol)或通訊埠(port)的資源時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request)。
傳統表單輸入
<form action="index.html" method='post'> |
當按下 submit
按鈕將表單送出後,HTML 會將表單內的資料以 URL?表單資訊
,如果有多組內容則會以 &
連接,並進行傳送。
AJAX POST
- 設定請求
XMLHttpRequest.open('post', 'API_URL', true);
- 要傳送表單資訊,method 須改為
psot
。
- 請求表頭
XMLHttpRequest.setRequestHeader(header, value);
- 要傳送內容的格式,header 屬性為
Content-type
-
HTML 表單(form)提交方式:
- 使用
POST
方法,並且設定 value 屬性為application/x-www-form-urlencoded
(HTML5 表單 預設編碼方式)。- 使用
POST
方法,並且設定 value 屬性為multipart/form-data
(傳送檔案)。- 常見的 application/json 或 application/octet-stream,使用上也是如出一轍
- 使用
- 發送請求
XMLHttpRequest.send();
XMLHttpRequest.send('表單資訊')
- HTML5 表單 預設編碼方式 -
Content-type: application/x-www-form-urlencoded
;表單資訊如有多個欄位需使用&
來連接。 - JSON傳遞 -
Content-type: application/json
;表單資訊使用JSON.stringify
轉型成 string 格式再進行傳送。
GET
const xhr = new XMLHttpRequest(); |
POST
-
HTML5 表單
使用 HTML5 表單 傳送資料到 serve ,表單資訊如有多個欄位需使用&
來連接。const xhr = new XMLHttpRequest();
const URL = 'https://hexschool-tutorial.herokuapp.com/api/signup';
xhr.open('post', URL, true);
// 設定檔頭格式為 HTML5 表單 格式
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('email=abcdd@gmail.com&password=123456'); -
JSON
使用 JSON 傳送資料到 serve ,JSON 需轉成字串格式。const xhr = new XMLHttpRequest();
const URL = 'https://hexschool-tutorial.herokuapp.com/api/signup';
const account = { email: 'ttest@hexschool.com', password: 'ttest12345678' }
xhr.open('post', URL, true);
// 設定檔頭格式為 JSON 格式
xhr.setRequestHeader('Content-type', 'application/json');
xhr.send(JSON.stringify(account));
Fetch API
以往都是依賴 XMLHttpRequest
。Fetch API 提供了一個能獲取包含跨網路資源在的資源介面,但這個新的 API 提供了更強更彈性的功能,其使用 Promise
作為基本構造要素。
並被廣泛使用在 Service Workers。Fetch 在設定 HTTP 相關的設定時, 也提供可讀性比較好的方法, 這些設定包括 CORS 以及其他 header。
Fetch 基本用法
fetch(input, {init}) |
fetch
會使用 ES6 的Promise
作回應.then(onFulfilled, onRejected)
作為下一步catch()
作為錯誤回應 (404, 500…)
- 回傳的為
Response
物件,需要使用不同資料類型使用對應方法,才能正確取得資料物件。
- input
- 定義你想要fetch的資源。
-
- 一個直接包含你希望fetch的資源的URL
- 一個
Request
對象
- init
- 可選對象,包含希望被包括到請求中的各種自定義選項。
-
屬性 設定值 method 請求的方法:GET、POST、PUT、DELETE、HEAD ( 預設 GET ) headers 要求相關的 Headers 物件 ( 預設 {} ) mode 請求的模式:cors、no-cors、same-origin、navigate ( 預設 cors ) referrer no-referrer、client 或一個 URL ( 預設 client ) credentials 請求中想要使用的credentials:omit、same-origin、include ( 預設 omit ) redirect 對重定向處理的模式:follow、error、manual ( 預設 manual ) cache 請求中想要使用的cache mode:default、no-store、reload、no-cache、force-cache ( 預設 default ) body 要加到要求中的內容。 - 可以是Blob, BufferSource, FormData, URLSearchParams, 或 USVString對象
- method 為 GET 或 HEAD 則不設定
屬性 | 設定值 |
---|---|
headers | 包含與 response 相關的 Headers 物件 |
ok | 成功回傳 true,不成功回傳 false |
status | 包含此 response 的狀態碼(例如:成功時為 200 )。 |
statusText | 包含狀態碼所對應的狀態文字 (例如: OK 對應 200)。 |
type | 包含此 response 的類型 (例如: basic, cors)。 |
url | 包含此 response 的 URL。 |
更多屬性和方法請參考 fetch Response
方法 | 設定值 |
---|---|
.json() |
讀取 Response 對象,並返回一個被解析為 JSON 格式的 Promise 對象。 |
.text() |
讀取 Response 對象,並返回一個被解析為 string 格式的 Promise 對象。 |
.blob() |
讀取 Response 對象,並返回一個被解析為 blob 格式的 Promise 對象 ( 非結構化物件資料,例如文字或二進位資料 )。 |
.arrayBuffer() |
讀取 Response 對象,並返回一個被解析為 arrayBuffer 格式的 Promise 對象( 有多少 bytes )。 |
.formData() |
讀取 Response 對象,並返回一個被解析為 formData 格式的 Promise 對象( 表單資料對應的的 Key 或 Value )。 |
.clone() |
建立 Response 的複製物件 |
.error() |
返回一個錯誤的新的 Response 對象。 |
更多屬性和方法請參考 fetch Response
GET
最簡單的方式只需要一個參數就是資料的 URL,fetch 會回傳一個包含 Response
的 promise ,針對不同資料類型使用對應方法處理此 Response
,return
此 Response
再將資料傳到下一個 then()
。
fetch('https://gank.io/api/random/data/福利/20') |
fetch()
函式會回傳一個 Promise,並在解析/完成 (resolve) 後,回傳Response
物件。Response
資訊內包含了請求的url
和用來判斷請求是否成功的status
狀態等。- 針對不同資料類型使用其對應方法,才能正確取得資料物件,
return
已解析的資料並傳給第二個.then()
接收。- return 使用的
.json()
,能夠將回傳的資料以物件的方式傳給第二個.then()
接收。 - 當回傳的資料無法轉換為物件時,則會將請求資料以字串
.text()
方式取出。
- return 使用的
POST
POST
請求需外在method
屬性內指定POST
方式。body
屬性指定要送出的資料。- 需要注意的是,
body
內的資料需使用JSON.stringify
將物件轉換成字串型態,否則server
端會無法正確取得資料。
- 需要注意的是,
const url = 'https://hexschool-tutorial.herokuapp.com/api/signup'; |
請求失敗
請求失敗須從 Response
的 status
的屬性值判斷,當 status
的值不等於 200 時,將在 .then()
中使用 throw
創建一個錯誤,並由 .catch()
接收錯誤內容。
fetch('https://httpbin.org/status/404', { |
框架
jQuery
jQueryAxios(推薦)
Axios參考
XMLHttpRequest — JavaScript 發送 HTTP 請求 (I)
網頁開發人員應了解的 HTTP 狀態碼
練習用APIList