什麼是 AJAX
AJAX ,英文全名是「Asynchronous JavaScript and XML」(非同步的 JavaScript 與 XML 技術)。
傳統的 Web 應用允許用戶端填寫表單(form),當送出表單時就向網頁伺服器傳送一個請求。伺服器接收並處理傳來的表單,然後送回一個新的網頁,但這個做法浪費了許多頻寬,因為在前後兩個頁面中的大部分 HTML 碼往往是相同的。由於每次應用的溝通都需要向伺服器傳送請求,應用的回應時間依賴於伺服器的回應時間。這導致了使用者介面的回應比本機應用慢得多。
與此不同,AJAX 應用可以僅向伺服器傳送並取回必須的資料,並在客戶端採用 JavaScript 處理來自伺服器的回應。因為在伺服器和瀏覽器之間交換的資料大量減少,伺服器回應更快了。同時,很多的處理工作可以在發出請求的客戶端機器上完成,因此 Web 伺服器的負荷也減少了。
應用
- 運用 XHTML+CSS 來表達資訊;
- 運用 JavaScript 操作 DOM(Document Object Model)來執行動態效果;
- 運用 XML 和 XSLT 操作資料
- 運用 XMLHttpRequest 或新的 Fetch API 與網頁伺服器進行非同步資料交換;
更簡單來說,就是取得遠端數據庫的資料。
透過 XMLHttpRequest 撈資料
如何使用 XMLHttpRequest
是物件跨瀏覽器撈資料,起手式程式碼:
1 | var xhr = new XMLHttpRequest(); |
另外在開方人員工具 console
中打上 xhr
,會看到下方物件,會看到一個 readyState
是 0,
代表已經產生一個 XMLHttpRequest
,但還沒有連到要取得的資料。
1 | XMLHttpRequest {onreadystatechange: null, readyState: 0, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …} |
要跟遠端資料庫要資料,一定要有這個 XMLHttpRequest
物件,告訴伺服器,我要跟你要資料了。再來透過宣告後的 xhr
變數來要資料,程式碼會這樣寫:
1 | xhr.open("格式", "AJAX 網址", 同步非同步); |
格式的部分比較常見會有下方兩個:
- get: 從 API 或後端資料。
- post: 傳送資料到伺服器跟後端要資料。
- true: 非同步 / false: 同步
‘格式’ 與 ‘AJAX 網址’ 要有引號,不然不會執行。
倘若今天要去撈台北市中有多少哺乳室的資料,程式碼會如下:
1 | xhr.open( |
open 開啟 XMLHttpRequest 物件
這時在 console
中打入 xhr
,會發現原本的 readyState
變成 1,代表有使用 open
開啟這個物件,但還沒有把資料傳送過去。
send 傳送資料
要把資料傳過去,要給 xhr.send 指令,因為這次只是要撈資料,沒有要傳送任何東西給數據庫,所以內容可以打成空值 (空的資料) (null),程式碼會長這樣:
1 | xhr.send(null); |
這時的 readyState
會是 4 ,代表已經完全接到數據資料,並把取得的資料放在 responseText
。
readyState 代碼解釋
- 0 - 產生一個 XMLHttpRequest,但還沒連接到想要取得的資料。
- 1 - 偵測到使用 open(),但尚未將資料送到資料庫。
- 2 - 偵測到使用 send 狀態。
- 3 - loading 狀態。(如果資料很大就會顯示,如果資料很小就會直接跳成 4 。
- 4 - 已經完全接到數據資料。
完整程式碼:
1 | var xhr = new XMLHttpRequest(); |
false 同步與 true 非同步的
以剛剛程式碼作為延續:
1 | var xhr = new XMLHttpRequest(); |
這時使用 console.log(xhr.responseText);
確認一下是否有撈到資料,理論是應該會撈到資料,但在開發人員工具中會顯示為沒有資訊,
原因是在第三個參數是同步與非同步的關係,
true 是非同步,不會等資料回傳,就繼續進行程式碼。
false 是同步 就會等到資料回傳,再繼續進行程式碼。如下圖:
但是一般專案為了網頁瀏覽順利,會先進行網頁讀取,讓資料陸續下載,所以大部分會使用 true,不然使用者會覺得網頁壞掉了。
onload 載入資料
因為 true
非同步不會馬上載到資料,所以會在新增一個語法,叫做 onload
,在上方透過開發人員工具中打入 xhr 也會看到物件 onload
,程式碼這樣寫:
1 | xhr.onload = function () { |
onload
是被動的語法,指的是在send
後,收到資料回傳,就執行這個onload
物件,這時就會進行資料下載。
在 HTML 先設定一個 .list
,作為等等顯示資料用。
1 | <div class="list"></div> |
倘若說今天要撈去 API 中的 資料,程式碼內容就可以設立這樣的條件:
1 | xhr.onload = function () { |
這樣就能得到一串 AJAX 所撈出的資料,並列出清單。
codepen: https://codepen.io/hnzxewqw/pen/NWqwaGp
- AJAX 主要做了以下幾件事情:
- 建立一個 XMLHttpRequest。(open)
- 跟對方要資料。(send)
- 回傳資料到自己的瀏覽器。(onload)
- 拿到資料後處理資料。
HTTP 狀態碼與 CORS 跨網域
比較常見到的有兩個狀態碼:
200-正確,有收到資料。
404-錯誤,找不到資料。
其他還有更多狀態碼可看保哥的文章 The Will Will Web
CORS 跨來源資源共用
CORS 跨來源資源共用,英文為 Cross-Origin Resource Sharing,是一種使用額外 HTTP 標頭令目前瀏覽網站的使用者代理取得存取其他來源(網域)伺服器特定資源權限的機制。當使用者代理請求一個不是目前文件來源——例如來自於不同網域(domain)、通訊協定(protocol)或通訊埠(port)的資源時,會建立一個跨來源 HTTP 請求(cross-origin HTTP request)。
於安全性考量,程式碼所發出的跨來源 HTTP 請求會受到限制。例如,XMLHttpRequest 及 Fetch 都遵守同源政策(same-origin policy)。這代表網路應用程式所使用的 API 除非使用 CORS 標頭,否則只能請求與應用程式相同網域的 HTTP 資源。
參考文章:
維基百科 https://zh.wikipedia.org/wiki/AJAX
MDN https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS