0%

JS 筆記 - 認識 AJAX、同步與非同步、HTTP狀態碼

ajax

什麼是 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
XMLHttpRequest {onreadystatechange: null, readyState: 0, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
onreadystatechange: null
readyState: 0 //還沒有取得資料
timeout: 0
withCredentials: false
upload: XMLHttpRequestUpload {onloadstart: null, onprogress: null, onabort: null, onerror: null, onload: null, …}
responseURL: "" //AJAX 網址
status: 0
statusText: ""
responseType: ""
response: "" //收到的內容
responseText: "" //收到遠端資料的文字
responseXML: null
onloadstart: null
onprogress: null
onabort: null
onerror: null
onload: null
ontimeout: null
onloadend: null
__proto__: XMLHttpRequest

要跟遠端資料庫要資料,一定要有這個 XMLHttpRequest 物件,告訴伺服器,我要跟你要資料了。再來透過宣告後的 xhr 變數來要資料,程式碼會這樣寫:

1
xhr.open("格式", "AJAX 網址", 同步非同步);

格式的部分比較常見會有下方兩個:

  • get: 從 API 或後端資料。
  • post: 傳送資料到伺服器跟後端要資料。
  • true: 非同步 / false: 同步

‘格式’ 與 ‘AJAX 網址’ 要有引號,不然不會執行。

倘若今天要去撈台北市中有多少哺乳室的資料,程式碼會如下:

1
2
3
4
5
xhr.open(
"get",
"https://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=5941f46b-4115-49b9-a511-18ea5b427676",
true
);

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
2
3
4
5
6
7
var xhr = new XMLHttpRequest();
xhr.open(
"get",
"https://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=e6831708-02b4-4ef8-98fa-4b4ce53459d9",
true
);
xhr.send(null);

false 同步與 true 非同步的

以剛剛程式碼作為延續:

1
2
3
4
5
6
7
var xhr = new XMLHttpRequest();
xhr.open(
"get",
"https://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=e6831708-02b4-4ef8-98fa-4b4ce53459d9",
true
);
xhr.send(null);

這時使用 console.log(xhr.responseText); 確認一下是否有撈到資料,理論是應該會撈到資料,但在開發人員工具中會顯示為沒有資訊,

非同步 true

原因是在第三個參數是同步與非同步的關係,
true 是非同步,不會等資料回傳,就繼續進行程式碼。
false 是同步 就會等到資料回傳,再繼續進行程式碼。如下圖:

同步 false

但是一般專案為了網頁瀏覽順利,會先進行網頁讀取,讓資料陸續下載,所以大部分會使用 true,不然使用者會覺得網頁壞掉了。

onload 載入資料

因為 true 非同步不會馬上載到資料,所以會在新增一個語法,叫做 onload,在上方透過開發人員工具中打入 xhr 也會看到物件 onload,程式碼這樣寫:

1
2
3
xhr.onload = function () {
console.log(xhr.responseText); //會撈到資料
};

onload 是被動的語法,指的是在 send 後,收到資料回傳,就執行這個 onload 物件,這時就會進行資料下載。

在 HTML 先設定一個 .list,作為等等顯示資料用。

1
<div class="list"></div>

倘若說今天要撈去 API 中的 資料,程式碼內容就可以設立這樣的條件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
xhr.onload = function () {
console.log(xhr.responseText); //有撈到資料
var data = JSON.parse(xhr.responseText); //字串轉成資料
console.log(data);
var dataLen = data.result.results.length;
console.log(dataLen);
var str = ""; //組字串
for (let i = 0; i < dataLen; i++) {
var location = data.result.results[i].locationName; //城市
var lowTemp = data.result.results[i].parameterName3; //最低溫
var highTemp = data.result.results[i].parameterName2; //最高溫
var weather = data.result.results[i].parameterName1; //天氣狀況
str +=
"<li>" +
location +
"氣溫: " +
lowTemp +
"~" +
highTemp +
"°C, 天氣: " +
weather +
"</li>"; //字串加總
}
list.innerHTML = str; //渲染在網頁上
};

這樣就能得到一串 AJAX 所撈出的資料,並列出清單。

codepen: https://codepen.io/hnzxewqw/pen/NWqwaGp

  • AJAX 主要做了以下幾件事情:
  1. 建立一個 XMLHttpRequest。(open)
  2. 跟對方要資料。(send)
  3. 回傳資料到自己的瀏覽器。(onload)
  4. 拿到資料後處理資料。

HTTP 狀態碼與 CORS 跨網域

404 ERROR

比較常見到的有兩個狀態碼:
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