什麼是 AJAX ?
AJAX 是「Asynchronous JavaScript and XML」(非同步的 JavaScript 與 XML 技術)的縮寫,簡單說就是網頁不用重新整理,就能即時地透過瀏覽器去跟伺服器溝通,撈出資料。
伺服器對 AJAX 資料請求回應通常是以三種資料格式其中之一(HTML、XML、JSON),最常與 Javascript 做搭配就是 JSON。
XMLHttpRequest 物件 — 跨瀏覽器撈資料
使用 XHR 物件可以在自己網頁上讀取遠端的 JSON 資料,最常見的用途是在註冊頁面驗證「用戶名」及「信箱」是否被重複使用。
設變數(xhr)
儲存一個 XMLHttpRequest 物件以抓取別人的資料,該物件裡面有很多事件跟屬性可以做應用,例如 onload / readyState 等。
var xhr = new XMLHttpRequest();
readyState 屬性的數值用以判斷目前讀取資料的狀態。
- 0 - 已經產生一個 XMLHttpRequest,但是還沒連結要撈的資料,接著下 open 指法來設定環境(有三個參數)
- 1 - 用了open,但是還沒傳資料
- 2 - 偵測到你有用 send
- 3 - 資料 loading 中
- 4 - 你撈到資料了,數據已經接收到
下 open 指令
xhr.open('格式', '讀取的網址', true);
第一個參數: 格式,讀取資料 ( get ) / 傳送資料到伺服器 ( post )
第三個參數: 同步與非同步
接著 xhr 的 readyState 會等於 1,代表我們用了.open() 但還沒把資料傳送過去。
傳送資料
xhr.send();
如果只是要讀取資料,則()內要打 null (空值)。
此時 readyState = 2,代表偵測到有用 send。
接下來,如果成功讀取到資料,則 XML 物件內的 responseText 屬性會把撈到的資料紀錄進去,此時 readyState = 4,代表已經成功撈到資料。
參照:XMLHttpRequest — JavaScript 發送 HTTP 請求 (I)
AJAX 非同步請求
通過 XMLHttpRequest 生成的請求可以有兩種方式來獲取資料,非同步模式或同步模式。XMLHttpRequest 物件的 open() 方法的第三個參數,true 代表非同步、false 代表同步,以下來介紹非同步及同步的意義。
非同步:可以同時進行多個任務,不需要等待上一個動作完成,就能讓程式碼繼續往下跑,等到請求資料完成才會執行 callback 函式。總之,在執行請求的同時,瀏覽器可以正常的執行其他事務的處理。
同步:必須等到請求完成才會繼續往下執行程式碼。
為了避免阻塞頁面,一般而言都會使用非同步請求,然而非同步請求在下了 send() 指令後,還需要一些時間 load 資料,在還沒撈到資料的情況下,程式碼繼續往下跑,那要怎樣才能順利將資料印出來呢?
解決方式:使用XMLHttpRequest 中的 onload 事件,該事件的意思是「當資料全部跑完以後,才會觸發此事件」。
xhr.onload = function(){console.log(xhr.responseText);//把抓到的資料物件化或陣列化,加以運用var str = JSON.parse(xhr.responseText);//選取 DOM,並渲染至網頁document.querySelector('要插入資料的 DOM .class 名稱').textContent = str[陣列編號].陣列屬性;}
HTTP 狀態碼
打開 chrome 開發工具選擇 Network 頁籤,重整一下可以看到該網頁讀取資料的狀況,其中有一個 status 欄,裡面的數字就是 HTTP 狀態碼,代表網頁連線的狀態。
以下先介紹 2 個狀態碼,其餘的狀態碼及更詳細的介紹,可以閱讀保哥的文章。
200:資料正確回傳
404:資料讀取錯誤
因此,剛剛上面的 onload 事件所觸發的函式,可以用 if 條件式把 HTTP 連線狀態加入判斷。
xhr.onload= function(){ console.log(xhr.responseText); if(xhr.status == 200){ var str = JSON.parse(xhr.responseText); document.querySelector('要插入資料的 DOM .class 名稱').textContent = str[陣列編號].陣列屬性; } else{ console.log('資料錯誤'); }}
步驟回顧
1. 建立了一個 XMLHttpRequest 物件
2. 傳送到伺服器要資料
3. 回傳資料到自己的瀏覽器
4. 拿到資料後,增加 onload 事件
5. 在 onload 事件上綁定函式,判斷 HTTP 連線是否正常,是的話將回傳的資料渲染至網頁,否的話畫面顯示資料錯誤
什麼是 Cross-Origin Resource Sharing (CORS)?
開了這個權限,其他開發者才能跨網域撈取資料。想知道某筆資料(JSON 或 API)有沒有開 CROS,可以上 test-cros.org 查詢。
post — 傳統表單輸入介紹
這個功能常用在註冊帳號時,將使用者輸入的資料跟資料庫做比對,檢查是否有重複的帳號。form 表單的 action 屬性要填入後端伺服器的網址,使用者輸入的資料將會被傳送到那個位址。按了傳送的按鈕後,該網頁的網址將會有所不同。
在原本的網址後面,會接「傳送至後端的網址」+「問號」+「表單欄位的 name」+「等於」+「使用者輸入的值(參數)」。數個 name 加參數的組合之間,會用 & 來做連接。
get 與 post 的差異
get:從瀏覽器發出請求,伺服器會回傳資料(在 responseText 裡面回傳一個物件)。
post:從瀏覽器發出請求,傳送資料時註明格式,若選擇用表單格式,則傳送資料的內容要仿照表單傳送後的網址*。
*也就是欄位1 name = 使用者輸入的值1 & 欄位2 name = 使用者輸入的值2 etc.
post 內容的格式,一般有兩種:
表單輸入格式:content-type application/x-www-form-urlencoded
JSON 格式:content-type application/json
傳送資料格式應依後端工程師的要求而定,有些情況可以直接丟 JSON 格式到後端,有些情況則是要用表單輸入格式傳送。
AJAX JSON 的傳遞
如果傳送資料到伺服器的格式要用 JSON 格式的話,方式跟表單輸入格式有點不同。
// 宣告變數儲存物件(將使用者輸入的資料寫入)var account = {email: 'abc123@gmail.com',password: ‘1234;}// xhrvar xhr = new XMLHttpResquest;xhr.open('post','伺服器URL',true);// 傳送資料的格式選擇為 JSONxhr.setRequestHeader('Content-type', 'application/json');// 用另一個變數儲存字串化的 JSONvar data = JSON.stringify(account);// 傳送xhr.send(data);
同理,收到伺服器回傳資料後要再作利用的時候,要把 responseText 裡的字串物件化(JSON.parse())。