一缴罗,1個HTTP請求一般由四部分組成:
1.HTTP請求的方法或動作疲陕,比如是GET還是POST
2.正在請求的URL孵睬,總得知道請求的地址是什么吧
3.請求頭,包含一些客戶端環(huán)境信息晒旅,身份驗證信息等
4.請求體顾瞪,也就是請求正文,請求正文中可以包含客戶提交的查詢字符串信息猪狈, 表單信息等
(1)GET請求:一般用于信息獲取
a.使用URL傳遞參數(shù)
b.對所發(fā)送信息的數(shù)量也是有限制的箱沦,一般在2000個字符
(2)POST請求:一般用于修改服務(wù)器上的資源
a.對所發(fā)送信息的數(shù)量無限制
一個HTTP響應(yīng)一般由三部分組成:
(1)一個數(shù)字和文字組成的狀態(tài)碼,用來顯示請求是成功還是失敗
(2)響應(yīng)頭雇庙,響應(yīng)頭也和請求頭一樣包含許多有用的信息谓形,例如服務(wù)器類型、日期時間疆前、內(nèi)容類型和長度等
(3)響應(yīng)體寒跳,也就是響應(yīng)正文
二、XMLHttpRequest對象
1.首先竹椒,新建一個XMLHttpRequest的實例 :
var xhr = new XMLHttpRequest();
2.然后童太,向遠(yuǎn)處主機(jī)發(fā)出一個HTTP請求:
xhr.open('GET','example.php');
xhr.send();
3.接著,等待遠(yuǎn)程主機(jī)做出回應(yīng)胸完。這時需要監(jiān)控XMLHttpRequest對象的狀態(tài)變化书释,指定回調(diào)函數(shù):
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
alert(xhr.responseText);
}else{
alert(xhr.statusText);
}
}
上面的代碼包含了老版本XMLHttpRequest對象的主要屬性;
xhr.readyState:XMLHttpRequest對象的狀態(tài)
0:請求未初始化,open還沒調(diào)用
1:服務(wù)器連接已建立舶吗,open已經(jīng)調(diào)用了
2:請求已接收征冷,也就是接收到頭信息了
3:請求處理中,也就是接收到響應(yīng)主體了
4:請求已完成誓琼,且響應(yīng)已就緒检激,也就是響應(yīng)完成了
xhr.status:服務(wù)器返回的狀態(tài)碼肴捉,等于200表示一切正常
responseText:獲得字符串形式的數(shù)據(jù)
responseXML:獲得XML形式的響應(yīng)數(shù)據(jù)
status和statusText:以數(shù)字和文本形式返回HTTP狀態(tài)碼:
1信息類 表示收到web瀏覽器請求,正在進(jìn)一步的處理中
2成功
3重定向
4客戶端錯誤
5服務(wù)器錯誤
getAllResponseHeader():獲取所有的響應(yīng)報頭
老版本的XMLHttpRequest對象的幾個缺點:
1.只支持文本數(shù)據(jù)的傳送叔收,無法用來讀取和上傳二進(jìn)制文件
2.傳送和接收數(shù)據(jù)時齿穗,沒有進(jìn)度信息,只能提示有沒有完成
3.受到“同域限制”饺律,只能向同一域名的服務(wù)器請求數(shù)據(jù)
新版本的功能
- 可以設(shè)置HTTP請求的時限
- 可以使用FormData對象管理表單數(shù)據(jù)
- 可以上傳文件
- 可以請求不同域名下的數(shù)據(jù)
- 可以獲取服務(wù)器端的二進(jìn)制數(shù)據(jù)
- 可以獲得數(shù)據(jù)傳輸?shù)倪M(jìn)度信息
HTTP請求時限:
xhr.timeout = 3000;
上面語句將等待時間設(shè)為3000毫秒窃页。過了這個時限,就自動停止HTTP請求复濒。
與之配套的還有一個timeout事件脖卖,用來指定回調(diào)函數(shù)
xhr.timeout = function(event){
alert('請求超時!');
}
目前巧颈,Opera畦木、Firefox和IE 10支持該屬性,IE 8和IE 9的這個屬性屬于XDomainRequest對象砸泛,而Chrome和Safari還不支持十籍。
三、FormData對象
ajax操作往往用來傳遞表單數(shù)據(jù)唇礁。為了方便表單處理勾栗,HTML 5新增了一個FormData對象,可以模擬表單盏筐。
首先围俘,新建一個FormData對象。
var formData = new FormData();
然后机断,為它添加表單項楷拳。
formData.append('username', '張三');
formData.append('id', 123456);
最后,直接傳送這個FormData對象吏奸。這與提交網(wǎng)頁表單的效果欢揖,完全一樣。
xhr.send(formData);
FormData對象也可以用來獲取網(wǎng)頁表單的值:
var form = document.getElementById('myform');
var formData = new FormData(form);
formData.append('secret', '123456'); // 添加一個表單項
xhr.open('POST', form.action);
xhr.send(formData);
四奋蔚、上傳文件
新版XMLHttpRequest對象她混,不僅可以發(fā)送文本信息,還可以上傳文件泊碑。
假定files是一個"選擇文件"的表單元素(input[type="file"])坤按,我們將它裝入FormData對象。
var formData = new FormData();
for (var i = 0; i < files.length;i++) {
formData.append('files[]', files[i]);
}
然后馒过,發(fā)送這個FormData對象臭脓。
xhr.send(formData);
五、跨域資源共享(CORS)
新版本的XMLHttpRequest對象腹忽,可以向不同域名的服務(wù)器發(fā)出HTTP請求来累。這叫做"跨域資源共享"(Cross-origin resource sharing砚作,簡稱CORS)。
使用"跨域資源共享"的前提嘹锁,是瀏覽器必須支持這個功能葫录,而且服務(wù)器端必須同意這種"跨域"。如果能夠滿足上面的條件领猾,則代碼的寫法與不跨域的請求完全一樣米同。
xhr.open('GET', 'http://other.server/and/path/to/script');
目前,除了IE 8和IE 9摔竿,主流瀏覽器都支持CORS面粮,IE 10也將支持這個功能。服務(wù)器端的設(shè)置继低,請參考《Server-Side Access Control》但金。
八、接收二進(jìn)制數(shù)據(jù)(方法A:改寫MIMEType)
老版本的XMLHttpRequest對象郁季,只能從服務(wù)器取回文本數(shù)據(jù)(否則它的名字就不用XML起首了),新版則可以取回二進(jìn)制數(shù)據(jù)钱磅。
這里又分成兩種做法梦裂。較老的做法是改寫數(shù)據(jù)的MIMEType,將服務(wù)器返回的二進(jìn)制數(shù)據(jù)偽裝成文本數(shù)據(jù)盖淡,并且告訴瀏覽器這是用戶自定義的字符集年柠。
xhr.overrideMimeType("text/plain; charset=x-user-defined");
然后,用responseText屬性接收服務(wù)器返回的二進(jìn)制數(shù)據(jù)褪迟。
var binStr = xhr.responseText;
由于這時冗恨,瀏覽器把它當(dāng)做文本數(shù)據(jù),所以還必須再一個個字節(jié)地還原成二進(jìn)制數(shù)據(jù)味赃。
for (var i = 0, len = binStr.length; i < len; ++i) {
var c = binStr.charCodeAt(i);
var byte = c & 0xff;
}
最后一行的位運(yùn)算"c & 0xff"掀抹,表示在每個字符的兩個字節(jié)之中,只保留后一個字節(jié)心俗,將前一個字節(jié)扔掉傲武。原因是瀏覽器解讀字符的時候,會把字符自動解讀成Unicode的0xF700-0xF7ff區(qū)段城榛。
六揪利、接收二進(jìn)制數(shù)據(jù)(方法B:responseType屬性)
從服務(wù)器取回二進(jìn)制數(shù)據(jù),較新的方法是使用新增的responseType屬性狠持。如果服務(wù)器返回文本數(shù)據(jù)疟位,這個屬性的值是"TEXT",這是默認(rèn)值喘垂。較新的瀏覽器還支持其他值甜刻,也就是說绍撞,可以接收其他格式的數(shù)據(jù)。
你可以把responseType設(shè)為blob罢吃,表示服務(wù)器傳回的是二進(jìn)制對象楚午。
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png');
xhr.responseType = 'blob';
接收數(shù)據(jù)的時候,用瀏覽器自帶的Blob對象即可尿招。
var blob = new Blob([xhr.response], {type: 'image/png'});
注意矾柜,是讀取xhr.response,而不是xhr.responseText就谜。
你還可以將responseType設(shè)為arraybuffer怪蔑,把二進(jìn)制數(shù)據(jù)裝在一個數(shù)組里。
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png');
xhr.responseType = "arraybuffer";
接收數(shù)據(jù)的時候丧荐,需要遍歷這個數(shù)組缆瓣。
var arrayBuffer = xhr.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteArray.byteLength; i++) {
// do something
}
}
更詳細(xì)的討論,請看Sending and Receiving Binary Data虹统。
七弓坞、進(jìn)度信息
新版本的XMLHttpRequest對象,傳送數(shù)據(jù)的時候车荔,有一個progress事件渡冻,用來返回進(jìn)度信息。
它分成上傳和下載兩種情況忧便。下載的progress事件屬于XMLHttpRequest對象族吻,上傳的progress事件屬于XMLHttpRequest.upload對象。
我們先定義progress事件的回調(diào)函數(shù)珠增。
xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
然后超歌,在回調(diào)函數(shù)里面,使用這個事件的一些屬性蒂教。
function updateProgress(event) {
if (event.lengthComputable) {
var percentComplete = event.loaded / event.total;
}
}
上面的代碼中巍举,event.total是需要傳輸?shù)目傋止?jié),event.loaded是已經(jīng)傳輸?shù)淖止?jié)凝垛。如果event.lengthComputable不為真禀综,則event.total等于0。
與progress事件相關(guān)的苔严,還有其他五個事件定枷,可以分別指定回調(diào)函數(shù):
load事件:傳輸成功完成。
abort事件:傳輸被用戶取消届氢。
error事件:傳輸中出現(xiàn)錯誤欠窒。
loadstart事件:傳輸開始。
loadEnd事件:傳輸結(jié)束,但是不知道成功還是失敗岖妄。