Ajax
和XMLHttpRequest
咱們一般將Ajax
等同於XMLHttpRequest
,但細究起來它們兩個是屬於不一樣維度的2個概念。javascript
如下是我認爲對
Ajax
較爲準確的解釋:(摘自what is Ajax)
AJAX stands for Asynchronous JavaScript and XML. AJAX is a new technique for creating better, faster, and more interactive web applications with the help of XML, HTML, CSS, and Java Script.phpAJAX is based on the following open standards:html
Browser-based presentation using HTML and Cascading Style Sheets (CSS).html5
Data is stored in XML format and fetched from the server.java
Behind-the-scenes data fetches using XMLHttpRequest objects in the browser.web
JavaScript to make everything happen.ajax
從上面的解釋中能夠知道:ajax
是一種技術方案,但並非一種新技術。它依賴的是現有的CSS
/HTML
/Javascript
,而其中最核心的依賴是瀏覽器提供的XMLHttpRequest
對象,是這個對象使得瀏覽器能夠發出HTTP
請求與接收HTTP
響應。chrome
因此我用一句話來總結二者的關係:咱們使用XMLHttpRequest
對象來發送一個Ajax
請求。json
XMLHttpRequest
的發展歷程XMLHttpRequest
一開始只是微軟瀏覽器提供的一個接口,後來各大瀏覽器紛紛效仿也提供了這個接口,再後來W3C對它進行了標準化,提出了XMLHttpRequest
標準。XMLHttpRequest
標準又分爲Level 1
和Level 2
。XMLHttpRequest Level 1
主要存在如下缺點:跨域
受同源策略的限制,不能發送跨域請求;
不能發送二進制文件(如圖片、視頻、音頻等),只能發送純文本數據;
在發送和獲取數據的過程當中,沒法實時獲取進度信息,只能判斷是否完成;
那麼Level 2
對Level 1
進行了改進,XMLHttpRequest Level 2
中新增瞭如下功能:
能夠發送跨域請求,在服務端容許的狀況下;
支持發送和接收二進制數據;
新增formData對象,支持發送表單數據;
發送和獲取數據時,能夠獲取進度信息;
能夠設置請求的超時時間;
固然更詳細的對比介紹,能夠參考阮老師的這篇文章,文章中對新增的功能都有具體代碼示例。
XMLHttpRequest
兼容性關於xhr
的瀏覽器兼容性,你們能夠直接查看「Can I use」這個網站提供的結果XMLHttpRequest兼容性,下面提供一個截圖。
從圖中能夠看到:
IE8/IE九、Opera Mini 徹底不支持xhr
對象
IE10/IE11部分支持,不支持 xhr.responseType
爲json
部分瀏覽器不支持設置請求超時,即沒法使用xhr.timeout
部分瀏覽器不支持xhr.responseType
爲blob
XMLHttpRequest
如何使用先來看一段使用XMLHttpRequest
發送Ajax
請求的簡單示例代碼。
function sendAjax() { //構造表單數據 var formData = new FormData(); formData.append('username', 'johndoe'); formData.append('id', 123456); //建立xhr對象 var xhr = new XMLHttpRequest(); //設置xhr請求的超時時間 xhr.timeout = 3000; //設置響應返回的數據格式 xhr.responseType = "text"; //建立一個 post 請求,採用異步 xhr.open('POST', '/server', true); //註冊相關事件回調處理函數 xhr.onload = function(e) { if(this.status == 200||this.status == 304){ alert(this.responseText); } }; xhr.ontimeout = function(e) { ... }; xhr.onerror = function(e) { ... }; xhr.upload.onprogress = function(e) { ... }; //發送數據 xhr.send(formData); }
上面是一個使用xhr
發送表單數據的示例,整個流程能夠參考註釋。
接下來我將站在使用者的角度,以問題的形式介紹
xhr
的基本使用。
我對每個問題涉及到的知識點都會進行比較細緻地介紹,有些知識點多是你平時忽略關注的。
在發送Ajax
請求(實質是一個HTTP請求)時,咱們可能須要設置一些請求頭部信息,好比content-type
、connection
、cookie
、accept-xxx
等。xhr
提供了setRequestHeader
來容許咱們修改請求 header。
void setRequestHeader(DOMString header, DOMString value);
注意點:
方法的第一個參數 header 大小寫不敏感,便可以寫成content-type
,也能夠寫成Content-Type
,甚至寫成content-Type
;
Content-Type
的默認值與具體發送的數據類型有關,請參考本文【能夠發送什麼類型的數據】一節;
setRequestHeader
必須在open()
方法以後,send()
方法以前調用,不然會拋錯;
setRequestHeader
能夠調用屢次,最終的值不會採用覆蓋override
的方式,而是採用追加append
的方式。下面是一個示例代碼:
var client = new XMLHttpRequest(); client.open('GET', 'demo.cgi'); client.setRequestHeader('X-Test', 'one'); client.setRequestHeader('X-Test', 'two');// 最終request header中"X-Test"爲: one, twoclient.send();
xhr
提供了2個用來獲取響應頭部的方法:getAllResponseHeaders
和getResponseHeader
。前者是獲取 response 中的全部header 字段,後者只是獲取某個指定 header 字段的值。另外,getResponseHeader(header)
的header
參數不區分大小寫。
DOMString getAllResponseHeaders();
DOMString getResponseHeader(DOMString header);
這2個方法看起來簡單,但卻到處是坑兒。
你是否遇到過下面的坑兒?——反正我是遇到了。。。
使用getAllResponseHeaders()
看到的全部response header
與實際在控制檯 Network
中看到的 response header
不同
使用getResponseHeader()
獲取某個 header
的值時,瀏覽器拋錯Refused to get unsafe header "XXX"
通過一番尋找最終在 Stack Overflow找到了答案。
緣由1:W3C的 xhr 標準中作了限制,規定客戶端沒法獲取 response 中的 Set-Cookie
、Set-Cookie2
這2個字段,不管是同域仍是跨域請求;
緣由2:W3C 的 cors 標準對於跨域請求也作了限制,規定對於跨域請求,客戶端容許獲取的response header字段只限於「simple response header
」和「Access-Control-Expose-Headers
」 (兩個名詞的解釋見下方)。
"
simple response header
"包括的 header 字段有:Cache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
;
"Access-Control-Expose-Headers
":首先得注意是"Access-Control-Expose-Headers
"進行跨域請求時響應頭部中的一個字段,對於同域請求,響應頭部是沒有這個字段的。這個字段中列舉的 header 字段就是服務器容許暴露給客戶端訪問的字段。
因此getAllResponseHeaders()
只能拿到限制之外(即被視爲safe
)的header字段,而不是所有字段;而調用getResponseHeader(header)
方法時,header
參數必須是限制之外的header字段,不然調用就會報Refused to get unsafe header
的錯誤。
xhr.response
的數據類型有些時候咱們但願xhr.response
返回的就是咱們想要的數據類型。好比:響應返回的數據是純JSON字符串,但咱們指望最終經過xhr.response
拿到的直接就是一個 js 對象,咱們該怎麼實現呢?
有2種方法能夠實現,一個是level 1
就提供的overrideMimeType()
方法,另外一個是level 2
才提供的xhr.responseType
屬性。
xhr.overrideMimeType()
overrideMimeType
是xhr level 1
就有的方法,因此瀏覽器兼容性良好。這個方法的做用就是用來重寫response
的content-type
,這樣作有什麼意義呢?好比:server 端給客戶端返回了一份document
或者是 xml
文檔,咱們但願最終經過xhr.response
拿到的就是一個DOM
對象,那麼就能夠用xhr.overrideMimeType('text/xml; charset = utf-8')
來實現。
再舉一個使用場景,咱們都知道xhr level 1
不支持直接傳輸blob二進制數據,那若是真要傳輸 blob 該怎麼辦呢?當時就是利用overrideMimeType
方法來解決這個問題的。
下面是一個獲取圖片文件的代碼示例:
var xhr = new XMLHttpRequest();//向 server 端獲取一張圖片xhr.open('GET', '/path/to/p_w_picpath.png', true);// 這行是關鍵!//將響應數據按照純文本格式來解析,字符集替換爲用戶本身定義的字符集xhr.overrideMimeType('text/plain; charset=x-user-defined'); xhr.onreadystatechange = function(e) { if (this.readyState == 4 && this.status == 200) { //經過 responseText 來獲取圖片文件對應的二進制字符串 var binStr = this.responseText; //而後本身再想方法將逐個字節還原爲二進制數據 for (var i = 0, len = binStr.length; i < len; ++i) { var c = binStr.charCodeAt(i); //String.fromCharCode(c & 0xff); var byte = c & 0xff; } } }; xhr.send();
代碼示例中xhr
請求的是一張圖片,經過將 response
的 content-type
改成'text/plain; charset=x-user-defined',使得 xhr
以純文本格式來解析接收到的blob 數據,最終用戶經過this.responseText
拿到的就是圖片文件對應的二進制字符串,最後再將其轉換爲 blob 數據。
xhr.responseType
responseType
是xhr level 2
新增的屬性,用來指定xhr.response
的數據類型,目前還存在些兼容性問題,能夠參考本文的【XMLHttpRequest
的兼容性】這一小節。那麼responseType
能夠設置爲哪些格式呢,我簡單作了一個表,以下:
值 | xhr.response 數據類型 |
說明 |
---|---|---|
"" |
String 字符串 |
默認值(在不設置responseType 時) |
"text" |
String 字符串 |
|
"document" |
Document 對象 |
但願返回 XML 格式數據時使用 |
"json" |
javascript 對象 |
存在兼容性問題,IE10/IE11不支持 |
"blob" |
Blob 對象 |
|
"arrayBuffer" |
ArrayBuffer 對象 |
下面是一樣是獲取一張圖片的代碼示例,相比xhr.overrideMimeType
,用xhr.response
來實現簡單得多。
var xhr = new XMLHttpRequest(); xhr.open('GET', '/path/to/p_w_picpath.png', true);//能夠將`xhr.responseType`設置爲`"blob"`也能夠設置爲`" arrayBuffer"`//xhr.responseType = 'arrayBuffer';xhr.responseType = 'blob'; xhr.onload = function(e) { if (this.status == 200) { var blob = this.response; ... } }; xhr.send();
雖然在xhr level 2
中,2者是共同存在的。但其實不難發現,xhr.responseType
就是用來取代xhr.overrideMimeType()
的,xhr.responseType
功能強大的多,xhr.overrideMimeType()
能作到的xhr.responseType
都能作到。因此咱們如今徹底能夠摒棄使用xhr.overrideMimeType()
了。
xhr
提供了3個屬性來獲取請求返回的數據,分別是:xhr.response
、xhr.responseText
、xhr.responseXML
xhr.response
默認值:空字符串""
當請求完成時,此屬性纔有正確的值
請求未完成時,此屬性的值多是""
或者 null
,具體與 xhr.responseType
有關:當responseType
爲""
或"text"
時,值爲""
;responseType
爲其餘值時,值爲 null
xhr.responseText
默認值爲空字符串""
只有當 responseType
爲"text"
、""
時,xhr
對象上纔有此屬性,此時才能調用xhr.responseText
,不然拋錯
只有當請求成功時,才能拿到正確值。如下2種狀況下值都爲空字符串""
:請求未完成、請求失敗
xhr.responseXML
默認值爲 null
只有當 responseType
爲"text"
、""
、"document"
時,xhr
對象上纔有此屬性,此時才能調用xhr.responseXML
,不然拋錯
只有當請求成功且返回數據被正確解析時,才能拿到正確值。如下3種狀況下值都爲null
:請求未完成、請求失敗、請求成功但返回數據沒法被正確解析時
ajax
請求的當前狀態在發一個ajax
請求後,若是想追蹤請求當前處於哪一種狀態,該怎麼作呢?
用xhr.readyState
這個屬性便可追蹤到。這個屬性是隻讀屬性,總共有5種可能值,分別對應xhr
不一樣的不一樣階段。每次xhr.readyState
的值發生變化時,都會觸發xhr.onreadystatechange
事件,咱們能夠在這個事件中進行相關狀態判斷。
xhr.onreadystatechange = function () { switch(xhr.readyState){ case 1://OPENED //do something break; case 2://HEADERS_RECEIVED //do something break; case 3://LOADING //do something break; case 4://DONE //do something break; }
值 | 狀態 | 描述 |
---|---|---|
0 |
UNSENT (初始狀態,未打開) |
此時xhr 對象被成功構造,open() 方法還未被調用 |
1 |
OPENED (已打開,未發送) |
open() 方法已被成功調用,send() 方法還未被調用。注意:只有xhr 處於OPENED 狀態,才能調用xhr.setRequestHeader() 和xhr.send() ,不然會報錯 |
2 |
HEADERS_RECEIVED (已獲取響應頭) |
send() 方法已經被調用, 響應頭和響應狀態已經返回 |
3 |
LOADING (正在下載響應體) |
響應體(response entity body )正在下載中,此狀態下經過xhr.response 可能已經有了響應數據 |
4 |
DONE (整個數據傳輸過程結束) |
整個數據傳輸過程結束,無論本次請求是成功仍是失敗 |
若是請求過了好久尚未成功,爲了避免會白白佔用的網絡資源,咱們通常會主動終止請求。XMLHttpRequest
提供了timeout
屬性來容許設置請求的超時時間。
xhr.timeout
單位:milliseconds 毫秒
默認值:0
,即不設置超時
不少同窗都知道:從請求開始 算起,若超過 timeout
時間請求尚未結束(包括成功/失敗),則會觸發ontimeout事件,主動結束該請求。
【那麼到底何時纔算是請求開始 ?】
——xhr.onloadstart
事件觸發的時候,也就是你調用xhr.send()
方法的時候。
由於xhr.open()
只是建立了一個鏈接,但並無真正開始數據的傳輸,而xhr.send()
纔是真正開始了數據的傳輸過程。只有調用了xhr.send()
,纔會觸發xhr.onloadstart
。
【那麼何時纔算是請求結束 ?】
—— xhr.loadend
事件觸發的時候。
另外,還有2個須要注意的坑兒:
能夠在 send()
以後再設置此xhr.timeout
,但計時起始點仍爲調用xhr.send()
方法的時刻。
當xhr
爲一個sync
同步請求時,xhr.timeout
必須置爲0
,不然會拋錯。緣由能夠參考本文的【如何發一個同步請求】一節。
xhr
默認發的是異步請求,但也支持發同步請求(固然實際開發中應該儘可能避免使用)。究竟是異步仍是同步請求,由xhr.open()
傳入的async
參數決定。
open(method, url [, async = true [, username = null [, password = null]]])
method
: 請求的方式,如GET/POST/HEADER
等,這個參數不區分大小寫
url
: 請求的地址,能夠是相對地址如example.php
,這個相對是相對於當前網頁的url
路徑;也能夠是絕對地址如http://www.example.com/example.php
async
: 默認值爲true
,即爲異步請求,若async=false
,則爲同步請求
在我認真研讀W3C 的 xhr 標準前,我總覺得同步請求和異步請求只是阻塞和非阻塞的區別,其餘什麼事件觸發、參數設置應該是同樣的,事實證實我錯了。
W3C 的 xhr標準中關於open()
方法有這樣一段說明:
Throws an "InvalidAccessError" exception if async is false, the JavaScript global environment is a document environment, and either the timeout attribute is not zero, the withCredentials attribute is true, or the responseType attribute is not the empty string.
從上面一段說明能夠知道,當xhr
爲同步請求時,有以下限制:
xhr.timeout
必須爲0
xhr.withCredentials
必須爲 false
xhr.responseType
必須爲""
(注意置爲"text"
也不容許)
若上面任何一個限制不知足,都會拋錯,而對於異步請求,則沒有這些參數設置上的限制。
以前說過頁面中應該儘可能避免使用sync
同步請求,爲何呢?
由於咱們沒法設置請求超時時間(xhr.timeout
爲0
,即不限時)。在不限制超時的狀況下,有可能同步請求一直處於pending
狀態,服務端遲遲不返回響應,這樣整個頁面就會一直阻塞,沒法響應用戶的其餘交互。
另外,標準中並無說起同步請求時事件觸發的限制,但實際開發中我確實遇到過部分應該觸發的事件並無觸發的現象。如在 chrome中,當xhr
爲同步請求時,在xhr.readyState
由2
變成3
時,並不會觸發 onreadystatechange
事件,xhr.upload.onprogress
和 xhr.onprogress
事件也不會觸發。
在上傳或者下載比較大的文件時,實時顯示當前的上傳、下載進度是很廣泛的產品需求。
咱們能夠經過onprogress
事件來實時顯示進度,默認狀況下這個事件每50ms觸發一次。須要注意的是,上傳過程和下載過程觸發的是不一樣對象的onprogress
事件:
上傳觸發的是xhr.upload
對象的 onprogress
事件
下載觸發的是xhr
對象的onprogress
事件
xhr.onprogress = updateProgress; xhr.upload.onprogress = updateProgress;function updateProgress(event) { if (event.lengthComputable) { var completedPercent = event.loaded / event.total; } }
void send(data);
xhr.send(data)
的參數data能夠是如下幾種類型:
ArrayBuffer
Blob
Document
DOMString
FormData
null
若是是 GET/HEAD請求,send()
方法通常不傳參或傳 null
。不過即便你真傳入了參數,參數也最終被忽略,xhr.send(data)
中的data會被置爲 null
.
xhr.send(data)
中data參數的數據類型會影響請求頭部content-type
的默認值:
若是data
是 Document
類型,同時也是HTML Document
類型,則content-type
默認值爲text/html;charset=UTF-8
;不然爲application/xml;charset=UTF-8
;
若是data
是 DOMString
類型,content-type
默認值爲text/plain;charset=UTF-8
;
若是data
是 FormData
類型,content-type
默認值爲multipart/form-data; boundary=[xxx]
若是data
是其餘類型,則不會設置content-type
的默認值
固然這些只是content-type
的默認值,但若是用xhr.setRequestHeader()
手動設置了中content-type
的值,以上默認值就會被覆蓋。
另外須要注意的是,若在斷網狀態下調用xhr.send(data)
方法,則會拋錯:Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest'
。一旦程序拋出錯誤,若是不 catch 就沒法繼續執行後面的代碼,因此調用 xhr.send(data)
方法時,應該用 try-catch
捕捉錯誤。
try{ xhr.send(data) }catch(e) { //doSomething... };
xhr.withCredentials
與 CORS
什麼關係咱們都知道,在發同域請求時,瀏覽器會將
cookie
自動加在request header
中。但你們是否遇到過這樣的場景:在發送跨域請求時,cookie
並無自動加在request header
中。
形成這個問題的緣由是:在CORS
標準中作了規定,默認狀況下,瀏覽器在發送跨域請求時,不能發送任何認證信息(credentials
)如"cookies
"和"HTTP authentication schemes
"。除非xhr.withCredentials
爲true
(xhr
對象有一個屬性叫withCredentials
,默認值爲false
)。
因此根本緣由是cookies
也是一種認證信息,在跨域請求中,client
端必須手動設置xhr.withCredentials=true
,且server
端也必須容許request
能攜帶認證信息(即response header
中包含Access-Control-Allow-Credentials:true
),這樣瀏覽器纔會自動將cookie
加在request header
中。
另外,要特別注意一點,一旦跨域request
可以攜帶認證信息,server
端必定不能將Access-Control-Allow-Origin
設置爲*
,而必須設置爲請求頁面的域名。
xhr
相關事件xhr
相關事件有不少,有時記起來還挺容易混亂。但當我瞭解了具體代碼實現後,就容易理清楚了。下面是XMLHttpRequest
的部分實現代碼:
interface XMLHttpRequestEventTarget : EventTarget { // event handlers attribute EventHandler onloadstart; attribute EventHandler onprogress; attribute EventHandler onabort; attribute EventHandler onerror; attribute EventHandler onload; attribute EventHandler ontimeout; attribute EventHandler onloadend; };interface XMLHttpRequestUpload : XMLHttpRequestEventTarget { };interface XMLHttpRequest : XMLHttpRequestEventTarget { // event handler attribute EventHandler onreadystatechange; readonly attribute XMLHttpRequestUpload upload; };
從代碼中咱們能夠看出:
XMLHttpRequestEventTarget
接口定義了7個事件:
onloadstart
onprogress
onabort
ontimeout
onerror
onload
onloadend
因此這麼一看就很清晰了:xhr
一共有8個相關事件:7個XMLHttpRequestEventTarget
事件+1個獨有的onreadystatechange
事件;而xhr.upload
只有7個XMLHttpRequestEventTarget
事件。
下面是我本身整理的一張xhr
相關事件觸發條件表,其中最須要注意的是 onerror
事件的觸發條件。
事件 | 觸發條件 |
---|---|
onreadystatechange |
每當xhr.readyState 改變時觸發;但xhr.readyState 由非0 值變爲0 時不觸發。 |
onloadstart |
調用xhr.send() 方法後當即觸發,若xhr.send() 未被調用則不會觸發此事件。 |
onprogress |
xhr.upload.onprogress 在上傳階段(即xhr.send() 以後,xhr.readystate=2 以前)觸發,每50ms觸發一次;xhr.onprogress 在下載階段(即xhr.readystate=3 時)觸發,每50ms觸發一次。 |
onload |
當請求成功完成時觸發,此時xhr.readystate=4 |
onloadend |
當請求結束(包括請求成功和請求失敗)時觸發 |
onabort |
當調用xhr.abort() 後觸發 |
ontimeout |
xhr.timeout 不等於0,由請求開始即onloadstart 開始算起,當到達xhr.timeout 所設置時間請求還未結束即onloadend ,則觸發此事件。 |
onerror |
在請求過程當中,若發生Network error 則會觸發此事件(若發生Network error 時,上傳尚未結束,則會先觸發xhr.upload.onerror ,再觸發xhr.onerror ;若發生Network error 時,上傳已經結束,則只會觸發xhr.onerror )。注意,只有發生了網絡層級別的異常纔會觸發此事件,對於應用層級別的異常,如響應返回的xhr.statusCode 是4xx 時,並不屬於Network error ,因此不會觸發onerror 事件,而是會觸發onload 事件。 |
當請求一切正常時,相關的事件觸發順序以下:
觸發xhr.onreadystatechange
(以後每次readyState
變化時,都會觸發一次)
觸發xhr.onloadstart
//上傳階段開始:
觸發xhr.upload.onloadstart
觸發xhr.upload.onprogress
觸發xhr.upload.onload
觸發xhr.upload.onloadend
//上傳結束,下載階段開始:
觸發xhr.onprogress
觸發xhr.onload
觸發xhr.onloadend
abort
/timeout
/error
異常的處理在請求的過程當中,有可能發生 abort
/timeout
/error
這3種異常。那麼一旦發生這些異常,xhr
後續會進行哪些處理呢?後續處理以下:
一旦發生abort
或timeout
或error
異常,先當即停止當前請求
將 readystate
置爲4
,並觸發 xhr.onreadystatechange
事件
若是上傳階段尚未結束,則依次觸發如下事件:
xhr.upload.onprogress
xhr.upload.[onabort或ontimeout或onerror]
xhr.upload.onloadend
xhr
事件中註冊成功回調?從上面介紹的事件中,能夠知道若xhr
請求成功,就會觸發xhr.onreadystatechange
和xhr.onload
兩個事件。 那麼咱們到底要將成功回調註冊在哪一個事件中呢?我傾向於 xhr.onload
事件,由於xhr.onreadystatechange
是每次xhr.readyState
變化時都會觸發,而不是xhr.readyState=4
時才觸發。
xhr.onload = function () { //若是請求成功 if(xhr.status == 200){ //do successCallback } }
上面的示例代碼是很常見的寫法:先判斷http
狀態碼是不是200
,若是是,則認爲請求是成功的,接着執行成功回調。這樣的判斷是有坑兒的,好比當返回的http
狀態碼不是200
,而是201
時,請求雖然也是成功的,但並無執行成功回調邏輯。因此更靠譜的判斷方法應該是:當http
狀態碼爲2xx
或304
時才認爲成功。
xhr.onload = function () { //若是請求成功 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ //do successCallback } }
終於寫完了......
看完那一篇長長的W3C的xhr 標準,我眼睛都花了......
但願這篇總結能幫助剛開始接觸XMLHttpRequest
的你。
最後給點擴展學習資料,若是你:
想真正搞懂XMLHttpRequest
,最靠譜的方法仍是看 W3C的xhr 標準;
想結合代碼學習如何用XMLHttpRequest
發各類類型的數據,能夠參考html5rocks上的這篇文章
想粗略的瞭解XMLHttpRequest
的基本使用,能夠參考MDN的XMLHttpRequest介紹;
想了解XMLHttpRequest
的發展歷程,能夠參考阮老師的文章;
想了解Ajax
的基本介紹,能夠參考AJAX Tutorial;
想了解跨域請求,則能夠參考W3C的 cors 標準;
想了解http
協議,則能夠參考HTTP Tutorial;