[JS] AJAX 筆記

Greta Ma
馬格蕾特的樹洞
7 min readAug 8, 2019

--

只是單純覺得 3.5 磁片很可愛

什麼是 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())。

AJAX 實作

宣告 XMLHttpRequest 物件

XMLHttpRequset + HTTP 狀態碼練習

setRequestHeader 資料格式

註冊頁練習

登入頁練習

--

--

Greta Ma
馬格蕾特的樹洞

正一類,大學一畢業就去當公務員,中間因緣際會轉職為前端工程師,之後又再任公職。這就是終點了嗎?我不那麼覺得。