Ajax是Asynchronous JavaScript+XML(異步JavaScript和XML)的縮寫。javascript
該名稱誕生於XML仍是數據傳輸首選格式的時期,如今這種狀況已經不復存在。儘管X在Ajax中表明XML, 但因爲JSON的許多優點,好比更加輕量以及做爲Javascript的一部分,目前 JSON 的使用比XML更加廣泛。JSON和XML都被用於在Ajax模型中打包信息。php
Ajax技術的核心是 XMLHttpRequest對象 (簡稱XHR)。XHR爲向服務器發送請求和解析服務器響應提供了流暢的接口。可以以異步方式從服務器取得更多信息,意味着用戶單擊後,不用刷新頁面也能得到新數據。便可以使用XHR對象取得新數據,而後經過DOM將新數據插入到頁面中。html
Ajax的好處:java
XMLHttpRequest對象的特色:jquery
只要xhr.readyState的值改變一次,就會觸發一次readystatechange事件。因此能夠利用該事件來檢測readyState發生變化後的值。es6
readystatechange事件處理程序只能經過xhr.onreadystatechange(DOM0級法法)來綁定才能確保跨瀏覽器的兼容性,由於並不是全部瀏覽器都支持DOM2級方法ajax
請求/響應過程的當前活動階段。該屬性可能的值爲:json
響應的HTTP狀態碼。一般是將 200<= 狀態碼 <300 或 status爲304做爲響應成功的標誌。api
Tips: 304表示請求的資源並無被修改,能夠直接使用瀏覽器緩存中的版本,因此也意味着響應有效。跨域
HTTP狀態的說明文字。
做爲響應主體被返回的文本。
初始化一個請求。
參數:
method:請求所使用的HTTP方法; 例如 "GET", "POST", "PUT", "DELETE"等
url:該請求要訪問的url。能夠是絕對地址,也能夠是相對於執行代碼的當前頁面的相對地址。
async:布爾值,是否異步發送請求,默認爲true
user(可選):用戶名,爲受權使用;默認爲空string.
password(可選):密碼,可選參數,爲受權使用;默認爲空string.
注意: 調用該方法並不會真正發送請求,只是啓動一個請求以備發送。
發送請求. 若是該請求是異步模式(默認),該方法會馬上返回. 相反,若是請求是同步模式,則直到請求的響應徹底接受之後,該方法纔會返回.
參數:
若是請求已經被髮送,則馬上終止請求。
調用這個方法後,XHR對象會中止觸發事件readystatechange,也再也不容許訪問任何與響應有關的對象屬性。
默認會發送的請求頭有:
該方法會設置自定義的請求頭部信息。
參數:
獲取相應響應頭字段的信息。
參數:
取得包含全部響應頭部信息的長字符串。
XMLHttpRequest level2級接口。
FormData爲序列化表單以及建立與表單格式相同的數據(用於XHR傳輸)提供了便利。
能夠這樣向FormData構造函數傳入表單元素來填入鍵值對:
var data = new FormData(document.forms[0]);
也可使用append方法添加任意多個鍵值對:
var data = new FormData(); data.append('name', 'Bonnie');
FormData對應數據的"Content-Type"爲"multipart/form-data",這也是該表頭的默認值,故使用FormData能夠沒必要明確爲Content-Type設置值,這是它的方便之處。
<div> <button id="btn">Apples</button> </div> <div id="target"> </div> <script> var button=document.getElementById("btn"); button.onclick=handleButtonPress; function handleButtonPress(e) { var xhr=new XMLHttpRequest();//建立XMLHttpRequest對象 xhr.onreadystatechange=function(){ if (xhr.readyState==4) {//xhr.readyState:該屬性表示請求/響應過程的當前活動階段,4爲完成,其值每變化一次都會觸發一次readystatechange事件 if ((xhr.status>=200&&xhr.status<300)||xhr.status==304) {//xhr.status:響應的狀態 //304狀態碼:客戶端已經執行了GET,但文件未發生變化,即服務器若是發現資源沒有改變過,那麼就會返回304,告訴瀏覽器,我沒變過,你去讀緩存吧,因而瀏覽器也不用從服務器拉數據了 document.getElementById("target").innerHTML=xhr.responseText;//xhr.responseText:做爲響應主體被返回的文本 } else{ document.getElementById("target").innerHTML="Request was unsuccessful: "+xhr.status; } } } xhr.open("GET","example.html",true);//要發送的類型、請求的URL和是否異步發送 xhr.send(null);//發送做爲請求主體要發送的數據 } </script>
Tips:GET請求常常會發生查詢字符串格式有問題的錯誤。解決方法:查詢字符串中每一個參數的名稱和值都必須使用encodeURIComponent()進行編碼。如下是一個向URL末尾添加查詢字符串參數的方法:
function addUrlParam(url, name, value) { url += ( url.indexOf('?') === -1 ? '?' : '&'); url += encodeURIComponent(name) + '=' + encodeURIComponent(value); }
<form id="fruitform" method="post" action="localhost:3000/form"> <p>Bsnanas:</p> <p><input name="bananas" value="2"/></p> <p>Apples:</p> <p><input name="apples" value="5"/></p> <p>Cherries:</p> <p><input name="cherries" value="20"/></p> <p>Total:</p> <div id="results">0 items</div> <button id="submit" type="submit">Submit Form</button> </form> <script> document.getElementById("submit").onclick=handleButtonPress; function handleButtonPress(e) { e.preventDefault();//取消按鈕提交表單的默認行爲 var form=document.getElementById("fruitform"); var formData=new Object(); var inputElements=document.getElementsByTagName("input"); for (var i=0;i<inputElements.length;i++) { formData[inputElements[i].name]=inputElements[i].value; }//將表單提交的數據轉換爲object類型 var xhr=new XMLHttpRequest();//建立XMLHttpRequest()對象 xhr.onreadystatechange= function(){//爲xhr.onreadystatechange設置事件監聽函數,readystatechange改變的時候觸發 if (xhr.readyState==4) { if (xhr.status>=200&&xhr.status<300||xhr.status==304) { var data=JSON.parse(xhr.responseText);//把JSON數據解析爲對象 document.getElementById("results").innerHTML="You ordered "+data.total+" items"; } } } xhr.open("post",form.action,true);//xhr.open()設置post方法,發送到的URL,是否異步 xhr.setRequestHeader("Content-Type","application/json");//設置請求的首部字段Content-Type爲application/json,告訴服務器在發送json數據 xhr.send(JSON.stringify(formData));//瀏覽器向服務器發送數據前,要把數據從Object轉換爲JSON字符串 } </script>
<script> document.getElementById("submit").onclick=handleButtonPress; function handleButtonPress(e) { e.preventDefault();//取消按鈕提交表單的默認行爲 var form=document.getElementById("fruitform"); var formData=""; var inputElements=document.getElementsByTagName("input"); for (var i=0;i<inputElements.length;i++) { formData+=inputElements[i].name+"="+inputElements[i].value+"&"; }//將表單提交的數據轉換爲編碼表單數據的默認方式(application/x-www-form-urlencoded編碼)。 var xhr=new XMLHttpRequest();//建立XMLHttpRequest()對象 xhr.onreadystatechange=function() {//爲xhr.onreadystatechange設置事件監聽函數,readystatechange改變的時候觸發 if(xhr.readyState == 4) { if(xhr.status >= 200 && xhr.status < 300 || xhr.status==304) { document.getElementById("results").innerHTML = xhr.responseText; } } } xhr.open("post",form.action,true);//xhr.open()設置post方法,發送到的URL,是否異步 xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");//設置請求的首部字段Content-Type爲application/json,告訴服務器在發送json數據 xhr.send(formData);//瀏覽器向服務器發送數據前,要把數據從Object轉換爲JSON字符串 } </script>
var data = new FormData(document.forms[0]);//能夠這樣向FormData構造函數傳入表單元素來填入鍵值對 /*也可使用append方法添加任意多個鍵值對。 var data = new FormData(); data.append('name', 'Bonnie'); */ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) { console.log(xhr.responseText) } } } xhr.open('POST', 'post.php', true); xhr.send(data);
http://api.jquery.com/jQuery.ajax/
執行Ajax請求。
$.ajax({ method: 'POST', url:'example.php', data: { name: 'Bonnie', age: 26 }, dataType:'json' }).done(function(msg){ console.log(msg); })
$.ajax('example.php') .done(function(){ alert('success'); }) .fail(function() { alert('error'); }) .always(function() { alert('complete') })
請求的地址。
這裏列出一些重點配置屬性:
default 'application/x-www-form-urlencoded; charset=UTF-8')
告訴服務器發送的數據類型。
default: false for same-domain requests, true for cross-domain requests)
是否跨域
Type: object or string or array)
要發送到服務器的數據。
default: Intelligent Guess (xml, json, script, or html)
Type: String
The type of data that you're expecting back from the server. If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string)
dataTye字段指明你指望從服務器返回的數據類型,若是沒有指定值,那麼jQuery將嘗試根據response的MIME類型來推斷該數據類型(XML MIME類型將產生XML, 1.4版本的JSON將產生JavaScript對象,1.4版本的script將產生script,其餘類型將返回字符串)
實踐中遇到的問題:
若是服務端php不指定header類型,那麼response數據默認分配成text/html;此時,若客戶端ajax不指定dataType,則在done裏接收的data爲string類型,這樣還須要JSON.parse對其進行處理
若是服務端php指定header類型爲application/json,那麼response的數據類型就爲JSON字符串;此時,若客戶端ajax不指定dataType,則在done裏接收的data就爲JavaScript object類型,這樣就不須要經過JSON.parse對其進行處理。
請求成功的回調函數
請求錯誤的回調函數
請求成功和失敗都會執行的回調函數。
Fetch API提供了一個獲取資源的藉口(包括跨域)。它提供了許多與XMLHttpRequest相同的功能,但被設計成更具可擴展性和高效性。
Fetch 的核心在於對 HTTP 接口的抽象,包括 Request,Response,Headers,Body,以及用於初始化異步請求的 global fetch。
[Service Workers]s(https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_APIs) 是大量使用Fetch的API的一個示例。
它返回一個 promise,這個promise會在請求響應後被resolve,並傳回Response對象。
當遇到網絡錯誤時,fetch()返回的promise會被reject,並傳回TypeError。
成功的fetch()檢查不只要包括promise被resolve,還要包括Response.ok屬性爲true.
fetch(urlStr) .then( res => res.json()) //res是一個response對象,並非咱們指望的json結果。爲了獲取JSON內容,咱們須要使用 json()方法。res.json()方法返回的也是一個promise對象,因此須要再一次地使用then() .then( myJson => { console.log(myJson) })
fetch(urlStr, { method: 'POST', // *GET, POST, PUT, DELETE, etc. body: JSON.stringify(data),//須要和請求頭字段Content-Type保持一致。這裏是發送json字符串 headers: { 'content-type': 'application/json' }, /* or: headers: new Headers({ 'Content-Type': 'application/json' }) */ }) .then(res => res.json()) .catch(error => console.error('Error:', error)) .then(data => console.log(data))
加上對請求是否成功的驗證:
fetch(urlStr, { method: 'POST', // *GET, POST, PUT, DELETE, etc. body: JSON.stringify(data),//須要和請求頭字段Content-Type保持一致。這裏是發送json字符串 headers: { 'content-type': 'application/json' }, }) .then(res => { if(res.ok) { return res.json(); } throw new Error('Network response was not ok.'); }) .catch(error => console.error('Error:', error.message)) .then(data => console.log(data))
Fetch API中的Body類表明Response/Request的body,容許你聲明其內容類型是什麼以及應該如何處理。
Body類由Response類和Request類實現,這爲對象response和request提供了一個相關聯的body(字節流)
只讀:包含一個指示body是否被讀取過的 Boolean 值。
使用一個 JSON 對象來讀取 Response流中的數據,並將bodyUsed狀態改成已使用。
返回:一個promise, resolve的結果是Json 對象 而非字符串(即通過JSON.parse()解析過的JSON字符串)
使用一個 FormData 對象來讀取 Response流中的數據,並將bodyUsed狀態改成已使用。
返回: 一個 Promise,resolve的結果是FormData 對象。
使用一個USVString (文本) 對象來讀取 Response流中的數據,並將bodyUsed狀態改成已使用。
返回:一個包含USVString對象 (text)的Promise,resolve的結果的編碼爲UTF-8。
注意: 其與Body.json()方法的區別:一樣是請求json字符串文本:
使用一個buffer數組來讀取 Response流中的數據,並將bodyUsed狀態改成已使用。
返回:A promise that resolves with an ArrayBuffer.
使用一個Blob對象來讀取Response流中的數據,並將bodyUsed狀態改成已使用。
返回:A promise that resolves with a Blob.
Headers 接口容許您對HTTP請求和響應頭執行各類操做。 這些操做包括檢索,設置,添加和刪除.
let myHeader = new Headers()
給現有的header添加一個值, 或者添加一個未存在的header並賦值.
從Headers對象中刪除指定header
從Headers對象中返回指定header的第一個值.
{ body: JSON.stringify(data), // must match 'Content-Type' header cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached credentials: 'same-origin', // include, same-origin, *omit headers: { 'user-agent': 'Mozilla/4.0 MDN Example', 'content-type': 'application/json' }, method: 'POST', // *GET, POST, PUT, DELETE, etc. mode: 'cors', // no-cors, cors, *same-origin redirect: 'follow', // manual, *follow, error referrer: 'no-referrer', // *client, no-referrer }
請求的方法
請求頭信息
請求的模式:
請求的憑據,如 omit、same-origin 或者 include。爲了在當前域名內自動發送 cookie , 必須提供這個選項。
可用的重定向模式: follow (自動重定向), error (若是產生重定向將自動終止而且拋出一個錯誤), 或者 manual (手動處理重定向).
能夠是 no-referrer、client或一個 URL
《JavaScript高級程序設計》21.1,21.2
https://developer.mozilla.org/zh-CN/docs/Web/Guide/AJAX
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
http://api.jquery.com/jQuery.ajax/
https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API#
https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
https://developer.mozilla.org/zh-CN/docs/Web/API/Body
https://developer.mozilla.org/zh-CN/docs/Web/API/Request
https://developer.mozilla.org/zh-CN/docs/Web/API/Response
https://developer.mozilla.org/zh-CN/docs/Web/API/WindowOrWorkerGlobalScope/fetch