在XHR誕生前,網頁要獲取客戶端和服務器的任何狀態更新,都須要刷新一次,在XHR誕生後就能夠徹底經過JS代碼異步實現這一過程。XHR的誕生也使最初的網頁製做轉換爲開發交互應用,拉開了WEB2.0的序幕。 javascript
XHR是一種瀏覽器API,極大簡化了異步通訊的過程,開發者並不須要關注底層的實現,由於瀏覽器會爲咱們完成這些工做,如鏈接管理、協議協商、HTTP請求格式化等等。最第一版本的XHR能力很是有限,只支持文本傳輸,處理上傳能力也不足,對於跨域請求也不支持。爲解決這些問題,W3C於2008年發佈了「XMLHttpRequest Level2」草案,新增了以下功能:java
2011年,W3C將「XMLHttpRequest Level2」規範與最初的「XMLHttpRequest」規範合併,全部XHR2新增的功能也都併入了原來的XHR API中,接口不變,功能加強。web
XMLHttpRequest 對象提供了對 HTTP 協議的徹底的訪問,包括作出 POST 和 HEAD 請求以及普通的 GET 請求的能力。XMLHttpRequest 能夠同步或異步地返回 Web 服務器的響應,而且可以以文本或者一個 DOM 文檔的形式返回內容。XHR接口強制要求每一個請求都具有嚴格的HTTP語義–應用提供數據和URL,瀏覽器格式化請求並管理每一個鏈接的完整生命週期,因此XHR僅僅容許應用自定義一些HTTP首部,但更多的首部是不能本身設定的,如:json
瀏覽器會拒絕絕對不安全的首部重寫,以保證應用不能假扮用戶代理、用戶或請求來源,如Origin由瀏覽器自動設置,Access-Control-Allow-Origin由服務器設置,若是接受該請求,不包含該字段便可,瀏覽器發出的請求將做廢。跨域
若是想要啓用cookie和HTTP認證,客戶端必須在發送請求時經過XHR對象發送額外的屬性(withCredentials),而服務器也須要以Access-Control-Allow-Credentials響應,表示容許應用發送隱私數據。一樣,若是客戶須要寫入或讀取自定義HTTP標頭或想要使用「非簡單的方法」的請求,那麼它必須首先經過發出一個預備請求,以獲取第三方服務器的許可,以下所示:瀏覽器
// Preflight request OPTIONS /resource.js HTTP/1.1 Host: thirdparty.com Origin: http://example.com Access-Control-Request-Method: POST Access-Control-Request-Headers: My-Custom-Header ... // Preflight response HTTP/1.1 200 OK Access-Control-Allow-Origin: http://example.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: My-Custom-Header ... (actual HTTP request)
W3C CORS規範定義的何時必須使用預備請求,「簡單」的請求能夠跳過它,但也有各類各樣場景須要使用預備請求,這就添加一次往返網絡延遲。可喜的是,一旦預備請求完成,它能夠由客戶端緩存,以免在後續請求進行相同的驗證。
在XHR中,能夠經過responseType-設置改變響應類型,以下所示:緩存
下面是經過XHR獲取一張圖片,並顯示到網頁上的示例:安全
var xhr = new XMLHttpRequest(); xhr.addEventListener("progress", updateProgress, false); xhr.addEventListener("load", transferComplete, false); xhr.addEventListener("error", transferFailed, false); xhr.addEventListener("abort", transferCanceled, false); xhr.open('GET', '/images/photo.webp'); xhr.responseType = 'blob'; xhr.onload = function() { if (this.status == 200) { var img = document.createElement('img'); img.src = window.URL.createObjectURL(this.response); img.onload = function() { window.URL.revokeObjectURL(this.src); } document.body.appendChild(img); } }; xhr.send();
上傳相關事件在 XMLHttpRequest.upload 對象上被觸發,像下面這樣,向服務器發送一個formdata格式數據:服務器
var formData = new FormData(); formData.append('id', 123456); formData.append('topic', 'performance'); var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", updateProgress); xhr.upload.addEventListener("load", transferComplete); xhr.upload.addEventListener("error", transferFailed); xhr.upload.addEventListener("abort", transferCanceled); xhr.open('POST', '/upload'); xhr.onload = function() { ... }; xhr.send(formData);
var blob = ...; const BYTES_PER_CHUNK = 1024 * 1024; const SIZE = blob.size; var start = 0; var end = BYTES_PER_CHUNK; while(start < SIZE) { var xhr = new XMLHttpRequest(); xhr.open('POST', '/upload'); xhr.onload = function() { ... }; xhr.setRequestHeader('Content-Range', start+'-'+end+'/'+SIZE); xhr.send(blob.slice(start, end)); start = end; end = start + BYTES_PER_CHUNK; }
注意:progress 事件在使用 file: 協議的狀況下是無效的。cookie