[WebAPIs] XMLHttpRequest(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="">
的方式來存取檔案。
- JSONP(JSON with padding):透過在 HTML 中加入
-
- CORS(Cross-Origin Resource Sharing):透過在伺服器上的設定讓其他網域的人能夠存取資料。
基本寫法
// 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
基本使用
// ./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 請求
// 寫法一
$.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
參考
- Using XMLHttpRequest @ MDN WebAPIs
- Getting Started AJAX @ MDN Web Guides
- HTML in XMLHttpRequest @ MDN WebAPIs
- XMLHttpRequest @ MDN WebAPIs