HTTP 定義 POST
來發送資料給伺服器,POST
適用於非等冪操作,若請求有副作用,多次 POST
請求的結果可以不同,它並非安全操作,可以用在修改資料庫的內容,或在伺服器上儲存檔案等。
如果要發送 POST
,則可以在非同步物件 open
時,將第一個參數設為 'POST'
,在這「之後」使用 setRequestHeader
設定內容類型,這是因為 POST
要發送的資料會放在請求的本體中,必須告知發送的資料類型為何,接著在 send
時,將要發送的資料,作為 send
的引數傳入。
例如,若發送表單類型資料,必須設置請求標頭 'Content-Type'
為 'application/x-www-form-urlencoded'
,以下是個示範:
...
let url = 'somewhere';
let queryString = 'a=10&b=20';
xmlHttp.open('POST', url);
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttp.send(queryString);
放在 POST 本體中的資料,也有可能是其他格式,例如 XML 或 JSON,你必須設定不同的請求標頭,這在之後還會說明。
在下面這個例子中,將先前對 XMLHttpRequest
的基本操作進行了簡單的封裝,並使用 POST
來實作〈使用 GET 請求〉 中第二個範例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
新增書籤:<br>
網址:<input id="url" type="text">
<span id="message" style="color:red"></span><br>
名稱:<input type="text">
<script type="text/javascript">
// 組合與編碼請求參數
function params(paraObj) {
return Object.keys(paraObj)
.map(name => {
let paraName = encodeURIComponent(name);
let paraValue = encodeURIComponent(paraObj[name]);
return `${paraName}=${paraValue}`.replace(/%20/g, '+');
})
.join('&');
}
// 對 XMLHttpRequest 做簡單封裝
class XHR {
constructor() {
let xhr = new XMLHttpRequest();
// 你還可以加入其他處理器的設置…
// 像是 loadstart、progress、abort、error、timeout、loadend 等
let handlers = {
'readystatechange' : new Set(),
'load' : new Set()
};
xhr.onreadystatechange = function(evt) {
handlers['readystatechange']
.forEach(handler => handler.call(xhr, evt));
};
xhr.onload = function(evt) {
handlers['load']
.forEach(handler => handler.call(xhr, evt));
};
this.xhr = xhr;
this.handlers = handlers;
}
addEvt(evtType, handler) {
this.handlers[evtType].add(handler);
return this;
}
removeEvt(evtType, handler) {
this.handlers[evtType].delete(handler);
return this;
}
open(method, url, paraObj, async = true, username = null, password = null) {
let openUrl = paraObj ? `${url}?${params(paraObj)}` : url;
this.xhr.open(method, openUrl, async, username, password);
return this;
}
addHeaders(headers) {
Object.keys(headers)
.forEach(name => this.xhr.setRequestHeader(name, headers[name]));
return this;
}
send(body = null) {
this.xhr.send(body);
return this;
}
}
document.getElementById('url').onblur = function() {
let reqString = params({
url : document.getElementById('url').value
});
let xhr = new XHR();
xhr.addEvt('load', evt => {
let req = evt.target;
if(req.status === 200 && req.responseText === 'existed') {
document.getElementById('message').innerHTML = 'URL 已存在';
}
})
.open('POST', 'POST-1.php')
.addHeaders({'Content-Type' : 'application/x-www-form-urlencoded'})
.send(reqString);
};
</script>
</body>
</html>
在事件的處理上,設計了 addEvt
可以加入處理器,以便與先前文件中看到的事件處理封裝具有相同的風格。