Ajax

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方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章