<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ## 13.1 XMLHttpRequest對象 **XMLHttpRequest對象**用來在瀏覽器與服務器之間傳送數據。 ~~~ var ajax = new XMLHttpRequest(); ajax.open('GET', 'http://www.example.com/page.php', true); ~~~ 上面代碼向指定的服務器網址,發出GET請求。 然后,AJAX指定回調函數,監聽通信狀態(readyState屬性)的變化。 ~~~ ajax.onreadystatechange = handleStateChange; ~~~ 一旦拿到服務器返回的數據,AJAX不會刷新整個網頁,而是只更新相關部分,從而不打斷用戶正在做的事情。 注意,AJAX只能向同源網址(協議、域名、端口都相同)發出HTTP請求,如果發出跨源請求,就會報錯。 雖然名字里面有XML,但是實際上,XMLHttpRequest可以報送各種數據,包括字符串和二進制,而且除了HTTP,它還支持通過其他協議傳送(比如File和FTP)。 ### 13.1.1 XHR的用法 ~~~ var xhr = new XMLHttpRequest(); // 指定通信過程中狀態改變時的回調函數 xhr.onreadystatechange = function(){ // 通信成功時,狀態值為4 if (xhr.readyState === 4){ if (xhr.status === 200){ console.log(xhr.responseText); } else { console.error(xhr.statusText); } } }; xhr.onerror = function (e) { console.error(xhr.statusText); }; // open方式用于指定HTTP動詞、請求的網址、是否異步 xhr.open('GET', '/endpoint', true); // 發送HTTP請求 xhr.send(null); ~~~ open方法的第三個參數是一個布爾值,表示是否為異步請求。如果設為false,就表示這個請求是同步的,下面是一個例子。 ~~~ var request = new XMLHttpRequest(); request.open('GET', '/bar/foo.txt', false); request.send(null); if (request.status === 200) { console.log(request.responseText); } ~~~ ### 13.1.2 XHR實例的屬性 **1. readyState 與 onreadystatechange** * `readyState`是一個只讀屬性,用一個整數和對應的常量,表示XMLHttpRequest請求當前所處的狀態。 ||| ||| | 0 (UNSEN)| 未初始化。表示XMLHttpRequest實例已經生成,但尚未調用open()方法。| | 1(OPENED)| 啟動。已經調用open()方法,但未調用send()方法,仍然可以使用setRequestHeader(),設定HTTP請求的頭信息。| | 2(HEADERS_RECEIVED)|發送。已經調用send()方法,并且頭信息和狀態碼已經收到,但未收到相應。| | 3(LOADING)| 接受。表示正在接收服務器傳來的body部分的數據,如果responseType屬性是text或者空字符串,responseText就會包含已經收到的部分信息。| | 4(DONE)| 完成。表示服務器數據已經完全接收,或者本次接收已經失敗了。| 在通信過程中,每當發生狀態變化的時候,readyState屬性的值就會發生改變。這個值每一次變化,都會觸發`readyStateChange`事件。 * `onreadystatechange屬性`指向一個回調函數,當readystatechange事件發生的時候,這個回調函數就會調用,并且XMLHttpRequest實例的readyState屬性也會發生變化。 另外,如果使用abort()方法,終止XMLHttpRequest請求,onreadystatechange回調函數也會被調用。 ~~~ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function(){ if(xhr.readyState == 4){ if((xhr.status >= 200 && xhr.status <300) || xhr.status == 304{ alert(xhr.responseText); }else{ alert("Request was unsuccessful: " + xhr.status); } } }; xhr.open("get","example.txt",true); xhr.send(null); ~~~ 上面代碼表示,只有readyState變為4時,才算確認請求已經成功,其他值都表示請求還在進行中。 必須在調用`open()`之前指定`onreadystatechange`事件處理程序才能確保跨瀏覽器兼容性。 **2. response 、responseType 、responseText與responseXML** * `response屬性`為只讀,返回接收到的數據體(即body部分)。它的類型可以是ArrayBuffer、Blob、Document、JSON對象、或者一個字符串,這由XMLHttpRequest.responseType屬性的值決定。 如果本次請求沒有成功或者數據不完整,該屬性就會等于null。 * `responseType屬性`用來指定服務器返回數據(xhr.response)的類型。 ||| ||| | “” | 字符串(默認值)| | arraybuffer | ArrayBuffer對象| | blob | Blob對象(二進制對象)| | document | Document對象| | json | JSON對象| | text | 字符串| text類型適合大多數情況,而且直接處理文本也比較方便,document類型適合返回XML文檔的情況,blob類型適合讀取二進制數據,比如圖片文件。 ~~~ var xhr = new XMLHttpRequest(); xhr.open('GET', '/path/to/image.png', true); xhr.responseType = 'blob'; xhr.onload = function(e) { if (this.status == 200) { var blob = new Blob([this.response], {type: 'image/png'}); // 或者 var blob = oReq.response; } }; xhr.send(); ~~~ 如果將這個屬性設為ArrayBuffer,就可以按照數組的方式處理二進制數據。 ~~~ var xhr = new XMLHttpRequest(); xhr.open('GET', '/path/to/image.png', true); xhr.responseType = 'arraybuffer'; xhr.onload = function(e) { var uInt8Array = new Uint8Array(this.response); for (var i = 0, len = binStr.length; i < len; ++i) { // var byte = uInt8Array[i]; } }; xhr.send(); ~~~ 如果將這個屬性設為“json”,支持JSON的瀏覽器,就會自動對返回數據調用JSON.parse()方法。也就是說,你從`xhr.response`屬性(注意,不是xhr.responseText屬性)得到的不是文本,而是一個**JSON對象**。 XHR2支持Ajax的返回類型為文檔,即xhr.responseType=”document” 。這意味著,對于那些打開`CORS`(跨域資源共享)的網站,我們可以直接用Ajax抓取網頁,然后不用解析HTML字符串,直接對XHR回應進行DOM操作。 * `responseText屬性`返回從服務器接收到的字符串,該屬性為只讀。如果本次請求沒有成功或者數據不完整,該屬性就會等于null。 如果服務器返回的數據格式是JSON,就可以使用responseText屬性。 ~~~ var data = ajax.responseText; data = JSON.parse(data); ~~~ * `responseXML屬性`返回從服務器接收到的Document對象,該屬性為只讀。如果本次請求沒有成功,或者數據不完整,或者不能被解析為XML或HTML,該屬性等于null。 返回的數據會被直接解析為DOM對象。 ~~~ /* 返回的XML文件如下 <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <book> <chapter id="1">(Re-)Introducing JavaScript</chapter> <chapter id="2">JavaScript in Action</chapter> </book> */ var data = ajax.responseXML; var chapters = data.getElementsByTagName('chapter'); ~~~ 如果服務器返回的數據,沒有明示Content-Type頭信息等于text/xml,可以使用overrideMimeType()方法,指定XMLHttpRequest對象將返回的數據解析為XML。 **3. status與statusText** * `status屬性`為只讀屬性,表示本次請求所得到的HTTP狀態碼,它是一個整數。一般來說,如果通信成功的話,這個狀態碼是200。 ||| ||| | 200 | OK,訪問正常| | 301 | Moved Permanently,永久移動| | 302 | Move temporarily,暫時移動| | 304 | Not Modified,未修改| | 307 | Temporary Redirect,暫時重定向| | 401 | Unauthorized,未授權| | 403 | Forbidden,禁止訪問| | 404 | Not Found,未發現指定網址| | 500 | Internal Server Error,服務器發生錯誤| 基本上,只有2xx和304的狀態碼,表示服務器返回是正常狀態。 ~~~ if (ajax.readyState == 4) { if ( (ajax.status >= 200 && ajax.status < 300) || (ajax.status == 304) ) { // Handle the response. } else { // Status error! } } ~~~ * `statusText屬性`為只讀屬性,返回一個字符串,表示服務器發送的狀態提示。不同于status屬性,該屬性包含**整個狀態信息**,比如”200 OK“。 **4. timeout** * `timeout屬性`等于一個整數,表示多少毫秒后,如果請求仍然沒有得到結果,就會自動終止。如果該屬性等于0,就表示沒有時間限制。 ~~~ var xhr = new XMLHttpRequest(); xhr.ontimeout = function () { console.error("The request for " + url + " timed out."); }; xhr.onload = function() { if (xhr.readyState === 4) { if (xhr.status === 200) { callback.apply(xhr, args); } else { console.error(xhr.statusText); } } }; xhr.open("GET", url, true); xhr.timeout = timeout; xhr.send(null); } ~~~ **5. 事件監聽接口** XMLHttpRequest第一版,只能對onreadystatechange這一個事件指定回調函數。該事件對所有情況作出響應。 XMLHttpRequest第二版允許對更多的**事件指定回調函數**。 ||| |||| | onloadstart| 請求發出| | onprogress | 正在發送和加載數據| | onabort | 請求被中止,比如用戶調用了abort()方法| | onerror | 請求失敗| | onload| 請求成功完成| | ontimeout | 用戶指定的時限到期,請求還未完成| | onloadend | 請求完成,不管成果或失敗| ~~~ xhr.onload = function() { var responseText = xhr.responseText; console.log(responseText); // process the response. }; xhr.onerror = function() { console.log('There was an error!'); }; ~~~ 注意,如果發生網絡錯誤(比如服務器無法連通),onerror事件無法獲取報錯信息,所以只能顯示報錯。 **6. withCredentials** * `withCredentials屬性`是一個布爾值,表示跨域請求時,用戶信息(比如Cookie和認證的HTTP頭信息)是否會包含在請求之中,默認為false。即向example.com發出跨域請求時,不會發送example.com設置在本機上的Cookie(如果有的話)。 如果你需要通過跨域AJAX發送Cookie,需要打開withCredentials。 ~~~ xhr.withCredentials = true; ~~~ 為了讓這個屬性生效,服務器必須顯式返回Access-Control-Allow-Credentials這個頭信息。 ~~~ Access-Control-Allow-Credentials: true ~~~ `withCredentials屬性`打開的話,不僅會發送Cookie,還會設置遠程主機指定的Cookie。注意,此時你的腳本還是遵守同源政策,無法從document.cookie或者HTTP回應的頭信息之中,讀取這些Cookie。 ### 13.1.3 XHR實例的方法 **1. abort()** `abort方法`用來終止已經發出的HTTP請求。 ~~~ ajax.open('GET', 'http://www.example.com/page.php', true); var ajaxAbortTimer = setTimeout(function() { if (ajax) { ajax.abort(); ajax = null; } }, 5000); ~~~ 上面代碼在發出5秒之后,終止一個AJAX請求。 **2. getAllResponseHeaders()** `getAllResponseHeaders方法`返回服務器發來的所有HTTP頭信息。格式為字符串,每個頭信息之間使用CRLF分隔,如果沒有受到服務器回應,該屬性返回null。 **3. getResponseHeader()** `getResponseHeader方法`返回HTTP頭信息指定字段的值,如果還沒有收到服務器回應或者指定字段不存在,則該屬性為null。 ~~~ function getHeaderTime () { console.log(this.getResponseHeader("Last-Modified")); } var oReq = new XMLHttpRequest(); oReq.open("HEAD", "yourpage.html"); oReq.onload = getHeaderTime; oReq.send(); ~~~ 如果有多個字段同名,則它們的值會被連接為一個字符串,每個字段之間使用“逗號+空格”分隔。 **4. open()** `open方法`用于指定發送HTTP請求的參數,它的使用格式如下,一共可以接受五個參數。 ~~~ void open( string method, string url, optional boolean async, optional string user, optional string password ); ~~~ ||| ||| | method | 表示HTTP動詞,比如“GET”、“POST”、“PUT”和“DELETE”。| | url | 表示請求發送的網址。| | async | 格式為布爾值,默認為true,表示請求是否為異步。如果設為false,則send()方法只有等到收到服務器返回的結果,才會有返回值。| | user | 表示用于認證的用戶名,默認為空字符串。| | password | 表示用于認證的密碼,默認為空字符串。| 如果對使用過open()方法的請求,再次使用這個方法,等同于調用abort()。 下面發送POST請求的例子。 ~~~ xhr.open('POST', encodeURI('someURL')); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onload = function() {}; xhr.send(encodeURI('dataString')); ~~~ 上面方法中,open方法向指定URL發出POST請求,send方法送出實際的數據。 下面是一個同步AJAX請求的例子。 ~~~ var request = new XMLHttpRequest(); request.open('GET', '/bar/foo.txt', false); request.send(null); if (request.status === 200) { console.log(request.responseText); } ~~~ **5. send()** `send方法`用于實際發出HTTP請求。如果不帶參數,就表示HTTP請求只包含頭信息,也就是只有一個URL,典型例子就是GET請求;如果帶有參數,就表示除了頭信息,還帶有包含具體數據的信息體,典型例子就是POST請求。 ~~~ ajax.open('GET' , 'http://www.example.com/somepage.php?id=' + encodeURIComponent(id) , true ); // 等同于 var data = 'id=' + encodeURIComponent(id)); ajax.open('GET', 'http://www.example.com/somepage.php', true); ajax.send(data); ~~~ 上面代碼中,GET請求的參數,可以作為查詢字符串附加在URL后面,也可以作為send方法的參數。 下面是發送POST請求的例子。 ~~~ var data = 'email=' + encodeURIComponent(email) + '&password=' + encodeURIComponent(password); ajax.open('POST', 'http://www.example.com/somepage.php', true); ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); ajax.send(data); ~~~ 如果請求是異步的(默認為異步),該方法在發出請求后會立即返回。如果請求為同步,該方法只有等到收到服務器回應后,才會返回。 注意,所有XMLHttpRequest的監聽事件,都必須在send()方法調用之前設定。 `send方法`的參數就是發送的數據。多種格式的數據,都可以作為它的參數。 ~~~ void send(); void send(ArrayBufferView data); void send(Blob data); void send(Document data); void send(String data); void send(FormData data); ~~~ 如果發送Document數據,在發送之前,數據會先被串行化。 發送二進制數據,最好使用`ArrayBufferView或Blob對象`,這使得通過Ajax上傳文件成為可能。 下面是一個上傳ArrayBuffer對象的例子。 ~~~ function sendArrayBuffer() { var xhr = new XMLHttpRequest(); var uInt8Array = new Uint8Array([1, 2, 3]); xhr.open('POST', '/server', true); xhr.onload = function(e) { ... }; xhr.send(uInt8Array.buffer); } ~~~ **FormData類型**可以用于構造表單數據。 ~~~ var formData = new FormData(); formData.append('username', '張三'); formData.append('email', 'zhangsan@example.com'); formData.append('birthDate', 1940); var xhr = new XMLHttpRequest(); xhr.open("POST", "/register"); xhr.send(formData); ~~~ 上面的代碼構造了一個formData對象,然后使用send方法發送。它的效果與點擊下面表單的submit按鈕是一樣的。 ~~~ <form id='registration' name='registration' action='/register'> <input type='text' name='username' value='張三'> <input type='email' name='email' value='zhangsan@example.com'> <input type='number' name='birthDate' value='1940'> <input type='submit' onclick='return sendForm(this.form);'> </form> ~~~ FormData也可以將現有表單構造生成。 ~~~ var formElement = document.querySelector("form"); var request = new XMLHttpRequest(); request.open("POST", "submitform.php"); request.send(new FormData(formElement)); ~~~ FormData對象還可以對現有表單添加數據,這為我們操作表單提供了極大的靈活性。 ~~~ function sendForm(form) { var formData = new FormData(form); formData.append('csrf', 'e69a18d7db1286040586e6da1950128c'); var xhr = new XMLHttpRequest(); xhr.open('POST', form.action, true); xhr.onload = function(e) { // ... }; xhr.send(formData); return false; } var form = document.querySelector('#registration'); sendForm(form); ~~~ FormData對象也能用來模擬File控件,進行文件上傳。 ~~~ function uploadFiles(url, files) { var formData = new FormData(); for (var i = 0, file; file = files[i]; ++i) { formData.append(file.name, file); // 可加入第三個參數,表示文件名 } var xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.onload = function(e) { ... }; xhr.send(formData); // multipart/form-data } document.querySelector('input[type="file"]').addEventListener('change', function(e) { uploadFiles('/server', this.files); }, false); ~~~ FormData也可以加入JavaScript生成的文件。 ~~~ // 添加JavaScript生成的文件 var content = '<a id="a"><b id="b">hey!</b></a>'; var blob = new Blob([content], { type: "text/xml"}); formData.append("webmasterfile", blob); ~~~ **6. setRequestHeader()** `setRequestHeader方法`用于設置HTTP頭信息。該方法必須在open()之后、send()之前調用。如果該方法多次調用,設定同一個字段,則每一次調用的值會被合并成一個單一的值發送。 ~~~ xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('Content-Length', JSON.stringify(data).length); xhr.send(JSON.stringify(data)); ~~~ 上面代碼首先設置頭信息Content-Type,表示發送JSON格式的數據;然后設置Content-Length,表示數據長度;最后發送JSON數據。 **7. overrideMimeType** 該方法用來指定服務器返回數據的MIME類型。該方法必須在send()之前調用。 傳統上,如果希望從服務器取回二進制數據,就要使用這個方法,人為將數據類型偽裝成文本數據。 ~~~ var xhr = new XMLHttpRequest(); xhr.open('GET', '/path/to/image.png', true); // 強制將MIME改為文本類型 xhr.overrideMimeType('text/plain; charset=x-user-defined'); xhr.onreadystatechange = function(e) { if (this.readyState == 4 && this.status == 200) { var binStr = this.responseText; for (var i = 0, len = binStr.length; i < len; ++i) { var c = binStr.charCodeAt(i); var byte = c & 0xff; // 去除高位字節,留下低位字節 } } }; xhr.send(); ~~~ 上面代碼中,因為傳回來的是二進制數據,首先用xhr.overrideMimeType方法強制改變它的MIME類型,偽裝成文本數據。字符集必需指定為“x-user-defined”,如果是其他字符集,瀏覽器內部會強制轉碼,將其保存成UTF-16的形式。字符集“x-user-defined”其實也會發生轉碼,瀏覽器會在每個字節前面再加上一個字節(0xF700-0xF7ff),因此后面要對每個字符進行一次與運算(&),將高位的8個位去除,只留下低位的8個位,由此逐一讀出原文件二進制數據的每個字節。 這種方法很麻煩,在XMLHttpRequest版本升級以后,一般采用指定responseType的方法。 ~~~ var xhr = new XMLHttpRequest(); xhr.onload = function(e) { var arraybuffer = xhr.response; // ... } xhr.open("GET", url); xhr.responseType = "arraybuffer"; xhr.send(); ~~~ ### 13.1.4 XHR實例的事件 **1. readyStateChange事件** readyState屬性的值發生改變,就會觸發readyStateChange事件。 我們可以通過onReadyStateChange屬性,指定這個事件的回調函數,對不同狀態進行不同處理。尤其是當狀態變為4的時候,表示通信成功,這時回調函數就可以處理服務器傳送回來的數據。 **2. progress事件** 上傳文件時,XMLHTTPRequest對象的upload屬性有一個progress,會不斷返回上傳的進度。 假定網頁上有一個progress元素。 ~~~ <progress min="0" max="100" value="0">0% complete</progress> ~~~ 文件上傳時,對upload屬性指定progress事件回調函數,即可獲得上傳的進度。 ~~~ function upload(blobOrFile) { var xhr = new XMLHttpRequest(); xhr.open('POST', '/server', true); xhr.onload = function(e) { ... }; // Listen to the upload progress. var progressBar = document.querySelector('progress'); xhr.upload.onprogress = function(e) { if (e.lengthComputable) { progressBar.value = (e.loaded / e.total) * 100; progressBar.textContent = progressBar.value; // Fallback for unsupported browsers. } }; xhr.send(blobOrFile); } upload(new Blob(['hello world'], {type: 'text/plain'})); ~~~ **3. load事件、error事件、abort事件** `load事件`表示服務器傳來的數據接收完畢,`error事件`表示請求出錯,`abort事件`表示請求被中斷。 ~~~ var xhr = new XMLHttpRequest(); xhr.addEventListener("progress", updateProgress); xhr.addEventListener("load", transferComplete); xhr.addEventListener("error", transferFailed); xhr.addEventListener("abort", transferCanceled); xhr.open(); function updateProgress (oEvent) { if (oEvent.lengthComputable) { var percentComplete = oEvent.loaded / oEvent.total; // ... } else { // 回應的總數據量未知,導致無法計算百分比 } } function transferComplete(evt) { console.log("The transfer is complete."); } function transferFailed(evt) { console.log("An error occurred while transferring the file."); } function transferCanceled(evt) { console.log("The transfer has been canceled by the user."); } ~~~ **4. loadend事件** abort、load和error這三個事件,會伴隨一個loadend事件,表示請求結束,但不知道其是否成功。 ~~~ req.addEventListener("loadend", loadEnd); function loadEnd(e) { alert("請求結束(不知道是否成功)"); } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看