1. XMLHttpRequest對象
XMLHttpRequest對象用於從JavaScript發出HTTP請求,下面是典型用法.
//新建一個XMLHttpRequest實例對象
var xhr = new XMLHttpRequest();
//指定通信過程中狀態改變時的回調函數
xhr.onreadystatechange = function() {
//通信成功時,狀態值爲4
var completed = 4;
if(xhr.readyState === completed){
if(xhr.status === 200){
//處理服務器發送過來的信息
}else{
//處理錯誤
}
}
};
//open方式用於指定HTTP動詞,請求的網址,是否異步
xhr.open('GET', '/endpoint', true);
//發送HTTP請求
xhr.send(null);
Open()
- 發送方法:”GET”,”POST”,”PUT”,”DELETE”
- 網址
- 是否異步,true表示異步,false表示同步
xhr.open('OPEN',9 encodeRUI('someURL'));
//設置HTTP請求的頭信息
xhr.setRequestHeader('content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {};
//用於實際翻出HTTP請求,如果不帶參數,只包含頭信息,如:GET;如果有參數,還帶有具體數據信息如:POST
xhr.send(encodeURI('dataString'));
send方法課發送許多類型的數據:
void send();
void send(ArrayBuffer data);
void send(Blob data);
void send(Document data);
void send(DOMString data);
void send(FormData data);
Blob類型可以用來發送二進制數據,這使得通過Ajax上傳文件成爲可能。
readyState屬性和readyStateChange事件
通信過程中,每當狀態發生改變,readyState屬性的值就會改變
這個值每改變一次,都會觸發readyStateChange事件.我們可以指定這個事件的回調函數,對不同狀態進行處理.
progress事件
上傳文件時,XMLHttpRequest對象的upload屬性有一個progress,會不斷返回上傳進度.
服務器返回的信息
status屬性
返回HTTP狀態碼.
responseText屬性
服務器返回的文本數據
setRequestHeader方法
用於設置HTTP頭信息
xhr.setRequestHeader('Content-type', 'application/json');
xhr.setRequestHeader('Content-Length', JSON.stringify(data).length);
xhr.send(JSON.stringify(data));
overrideMimeType方法
指定服務器返回數據的MIME類型.
如果希望從服務器取回二進制數據,就要使用這個方法,認爲將數據類型僞裝成文本數據.
responseType屬性
XMLHttpRequest對象有一個responseType屬性,用來指定服務器返回數據(xhr.response)的類型.
- ‘text’:返回了性爲字符串,默認值
- ‘arraybuffer’: 返回類型爲ArrayBuffer
- ‘blob’: 返回類型爲Blob
- ‘document’: 返回類型爲Document
- ‘json’: 返回類型爲JSON object
文件上傳
<form id="file-form" action="handler.php" method="post">
<input type="file" id="file-select" name="photos[]" multiple />
<button type="submit" id="upload-button">上傳</button>
</form>
HTML代碼中,file控件的multiple屬性
,可以指定一次選多個文件
file對象的files屬性
,返回一個FileList對象
var fileSelect = document.getElementById('file-select');
var files = fileSelect.files;
//新建一個FormData對象實例,模擬發送到服務器的表單數據
var formData = new FormData();
for ( var i = 0;i < files.length;i++ ){
var file = file[i];
if(!file.type.match('image.*')) {
continue;
}
formData.append('photos[]', file, file.name);
}
//最後使用Ajax方法向服務器上傳文件
var xhr = new XMLHttpRequest();
xhr.open('POST', 'handler.php', true);
xhr.onload = function() {
if(xhr.status !== 200) {
alert('An error occurred!');
}
}
xhr.send(formData);
//除了FormData接口上傳,也可以直接使用FileAPI上傳
var file = document.getElementById('test-input').files[0];
var xhr = new XMLHttpRequest();
xhr.open('POST', 'muserver.uploads');
xhr.setRequestHeader('Content-Type', file.type);
xhr.send(file);
FormData對象的append方法,除了可以添加文件,還可以添加二進制對象(Blob)或者字符串。第一個參數是表單的控件名,第二個參數是實際的值,第三個參數是可選的,通常是文件名。
JSONP
用於服務器與客戶端之間的數據傳輸,主要爲了規避瀏覽器的同域限制.
function addScriptTag(src){
var scipt = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function(){
addScriptTag("HTTP://example.com/ip?callback=foo");
}
function foo(data) {
console.log('your public IP address is: ' + data.ip);
}
許多服務器支持JSONP指定回調函數的名稱,直接將JSON數據放入回調函數的參數,如此一來就省略了將字符串解析爲JSON對象的步驟。
jQuery的 getJSON方法就是JSONP的一個應用
$.getJSON("http://example.com/api", function(data){})
CORS “跨域資源共享”(Cross-origin resource sharing)
允許JavaScript代碼向另一個域名發出XMLHttpRequest請求,從而克服了傳統上Ajax只能在同一個域名下使用的限制(same origin security policy)
//檢查瀏覽器是否支持的代碼如下
var request = new XMLHttpRequest();
if("withCredentials" in request) {
}
服務器迴應的都有一個:Access-Control-Allow-Origin頭信息.
Fetch API
Ajax操作所用的XMLHttpRequestRquest對象,已經有十多年的歷史了,它的API設計並不是很好,輸入、輸出、狀態都在同一個接口管理,容易出現混亂的代碼.Fetch API是一種新規範,用來取代XMLHttpRequest對象.它主要有兩個特定,一是簡化接口,將API分散在幾個不同的對象上,二是返回Promise對象,避免嵌套的回調函數.
檢查瀏覽器是否部署了這個API的代碼如下:
if (fetch in window){
//支持
}else {
//不支持
}
fetch API簡單例子
var URL = 'http://some/path';
fetch(URL).then(function(response) {
return response.json();
}).then(function(json) {
someOperator(json);
});
上面代碼向服務器請求JSON文件,獲取後再做進一步處理.
function reqListener() {
var data = JSON.parse(this.responseText);
console.log(data);
}
function reqError(err) {
console.log('Fetch Error : -S', err);
}
var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
Fetch操作
fetch('./api/some.json')
.then(function(response) {
if(response.status !== 200){
console.log('請求失敗,狀態碼: ' + response.status);
return;
}
response.json().then(function(data) {
console.log(data);
});
}).catch(function(err){
console.log('出錯: ', err);
});
因爲HTTP請求返回的response對象是一個Stream對象,所以需要使用response.json方法轉爲JSON格式,不過這個方法返回的是一個Promise對象。
* fetch()*
fetch方法的第一個參數可以是URL字符串,也可以是後文要講到的Request對象實例.Fetch方法返回一個Promise對象,並將一個response對象傳給回調函數.
發出POST請求的寫法如下:
fetch("http://www.example.org/submit.php", {
method: "POST",
header: {
"content-Type": "application/x-www-form-urlencoded"
},
body: "firstName=nik&sdfs=blue&password=sdfs"
}).then(function(res) {
if(res.ok) {
console.log("Perfect!your settings are saved");
} else if(res.status == 401) {
console.log("oops,You are not authorized.");
}
},function(e) {
console.log("Error submitting form!");
});
Headers
Fetch API引入三個新的對象(構造函數): Header,Request和Response.
reqHeaders = new Headers({
"Content-Type": "text/plain",
"Content-Length": content.length.toString(),
"x-Custom-Header": "ProcessThisImmediately"
});
//headers實例構造Response方法
var response = new Response(
JSON.stringify({photos: {photo: []}}),
{'status': 200, headers: headers}
);
response.json().then(function(json) {
insertPhotos(json);
});
Request
//Request對象用來構造HTTP請求
var req = new Request('/index.html');
req.method //"GET"
req.url //"http://example.com/index.html"
//Request對象的第二個參數,表示配置對象
var uploadReq = new Request("/uploadImage", {
method: "POST",
headers: {
"Content-Type": "image/png",
},
body: "image data"
});
Response
- status:整數值,表示狀態碼(比如200)
- statusText:字符串,表示狀態信息,默認是“OK”
- ok:布爾值,表示狀態碼是否在200-299的範圍內
- headers:Headers對象,表示HTTP迴應的頭信息
- url:字符串,表示HTTP請求的網址
- type:字符串,合法的值有五個basic、cors、default、error、opaque。basic表示正常的同域請求;cors表示CORS機制的跨域請求;error表示網絡出錯,無法取得信息,status屬性爲0,headers屬性爲空,並且導致fetch函數返回Promise對象被拒絕;opaque表示非CORS機制的跨域請求,受到嚴格限制。
Response對象還有兩個靜態方法。
- Response.error() 返回一個type屬性爲error的Response對象實例
- Response.redirect(url, status) 返回的Response對象實例會重定向到另一個URL
body屬性
Request對象和Response對象都有body屬性,表示請求的內容。body屬性可能是以下的數據類型。
- ArrayBuffer
- ArrayBufferView (Uint8Array等)
- Blob/File
- string
- URLSearchParams
- FormData
Request對象和Response對象都提供以下方法,用來讀取body。
- arrayBuffer()
- blob()
- json()
- text()
- formData()
Request對象和Response對象都有bodyUsed屬性,返回一個布爾值,表示body是否被讀取過。
如果希望多次使用body屬性,可以使用Response對象和Request對象的clone方法。