PJCHENder 未整理筆記

[WebAPIs] XMLHttpRequest(AJAX)

2018-06-07

[WebAPIs] AJAX (XMLHttpRequest)

@(JavaScript)[JavaScript, WebAPIs, AJAX]

keywords: AJAX, WebAPIs, jQuery

觀念

  • 如果你送出多個 AJAX 請求,那麼 callback 執行的順序是不一定的。
  • AJAX request 只能在網路伺服器(web server)上運作,沒辦法透過直接在電腦上點兩下打開檔案來運作。
  • 每做一次 AJAX 請求就要建立一個 XHR Object
  • AJAX 的使用被限制在 “same origin policy”,也就是無法透過 AJAX 和不同的 webserver 進行請求,這也包含了不同的 subdomain、http 對 https、不同的 port、不同的 host。
  • 有幾種方式可以解決 same origin policy 的問題:
    • 透過 web server 向其他的 web server 請求資料(web proxy)。
    • JSONP(JSON with padding):透過在 HTML 中加入 <link href=""><script src=""> 的方式來存取檔案。
    • CORS(Cross-Origin Resource Sharing):透過在伺服器上的設定讓其他網域的人能夠存取資料。

基本寫法

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
26
27
28
// Create an XMLHTTP Request Object(XHR Object):透過瀏覽器建立一個包含傳送和接收資料方法的物件
var xhr = new XMLHttpRequest();

// Define a callback function:當接受到回傳的資料時要做什麼樣的處理
// readyState 是用來指稱 AJAX 狀態的變化;status 則是用來指稱 request 的狀態(Http Status)[參考資料] W3Schools

// Open a Request:告訴瀏覽器你要送出 request 的方法和目的地(URL)
xhr.open('GET', 'sidebar.html');

xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
document.getElementById('ajax').innerHTML = xhr.responseText;
} else if (xhr.status === 404) {
// Do something when file not found
}
}
};

xhr.onload = function() {
// Do something when response loaded
};

// Send the Request:
function sendAJAX() {
xhr.send();
document.getElementById('load').style.display = 'none';
}

AJAX by jQuery

keywords: AJAX

此部分套用在 Rails 中時,可以參考筆記 [Rails AJAX 小技巧](/Users/pjchen/Projects/Note/source/_posts/Ruby on Rails/[Rails] AJAX 小技巧.md)。

jQuery AJAX @ jQuery API
程式範例 @ Gist

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ./app/views/products/index.html.erb
$(function () {
$('#send-ajax').on('click', function (e) {
e.preventDefault();

$.ajax({
beforeSend: function (xhr) { xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content')) }, // 傳送 Rails Token
url: $(this).attr("href"), // get the link of <a>
type: 'GET', // request METHOD
dataType: 'json', // 希望 server 回傳的資料類型
processData: false, // 是否將 data 轉成 query string
contentType: false, // 指定傳送到 server 的資料類型
data: { // data send to backend
status: 'send request '
}
}).done(function (response) {
console.log('success', response)
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log('fail', textStatus, errorThrown)
})
})
});

contentType(default: 'application/x-www-form-urlencoded; charset=UTF-8'

使用這裡所指定的 contentType 類型來傳送資料到伺服器,預設是 application/x-www-form-urlencoded; charset=UTF-8。當設定成 false 時,jQuery 則不會傳送任何 content type header。

  • 對於 cross-domain 的請求,傳送 content type 為 application/x-www.form-urlencoded, multipart/form-data, text/plain 以外的類型時,會促使瀏覽器發送 OPTIONS 的先導請求到伺服器。
  • 根據 W3C 的標準,編碼格式總是為 UTF-8,指定其他格式並沒有作用。

dataType (default: Intelligent Guess (xml, json, script, or html))

希望伺服器回傳的資料類型,如果未設定,則 jQuery 會試著根據回應的 MIME 類型來設定,其他可用的格式包括:xml, html, script, json, jsonp, text

processData (default: true)

預設的情況下,所有的 data 項目內的物件都會被處理並轉換成 query string 以符合預設的 content-type application/x-www-form-urlencoded,因此如果你希望傳送 DOMDocument 或其他不被前處理的資料,這可將此選項設為 false

cache(default: true

如果設成 false ,將會在發送請求時強迫瀏覽器不要快取。但這只對 HEAD 和 GET 請求有作用,這是透過在 GET 的參數中添加 _={timestamp}

使用 .then() 串接 AJAX 請求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 寫法一
$.ajax({...}).then(function(){
return $.ajax({...});
}).then(function(){
return $.ajax({...});
}).then(function(){
return $.ajax({...});
}).then(function(){
return $.ajax({...});
});

// 方法二
function first() {
return $.ajax(...);
}
function second(data, textStatus, jqXHR) {
return $.ajax(...);
}
function third(data, textStatus, jqXHR) {
return $.ajax(...);
}
function main() {
first().then(second).then(third);
}

Chain multiple “then” in jQuery.when @ StackOverflow
How do I chain three asynchronous calls using jQuery promises? @ StackOverflow

參考

掃描二維條碼,分享此文章