AJAX即「Asynchronous JavaScript and XML」(異步的JavaScript與XML技術),指的是一套綜合了多項技術的瀏覽器端網頁開發技術,包含了HTML、CSS、JavaScript、DOM、XML等技術。Aiax 只是一個哥們「發明」的縮寫,這個新術語用來描述一種使用現有技術集合的一個名稱。多項技術中最重要的是 XMLHttpRequest 對象,稍後會介紹到它。html
若是不使用 Ajax,仔細觀察一個Form的提交,你就會發現,一旦用戶點擊「Submit」按鈕,表單開始提交,瀏覽器就會刷新頁面,而後會跳到新頁面裏告訴你操做是成功了仍是失敗了。若是失敗了,還要返回表單填寫頁,有些信息會丟失,須要從新填寫,這對用戶體驗極其不友好。ajax
這是Web的運做原理:一次HTTP請求對應一個頁面。json
若是要讓用戶留在當前頁面中,同時發出新的HTTP請求,就必須用JavaScript發送這個新請求,接收到數據後,再用JavaScript更新頁面,這樣一來,用戶就感受本身仍然停留在當前頁面,數據卻能夠不斷地更新。後端
也就是說,當使用了 Ajax 後,能夠在不從新刷新頁面的狀況下與服務器通訊,交換數據,更新頁面, 這樣可以快速地將數據更新呈如今用戶界面上,這使得程序可以更快地迴應用戶的操做。api
能夠利用 Ajax 的特性作以下事情:數組
使用 AJAX 技術中的 XMLHttpRequest 對象與服務器通訊,交換數據。數據的格式可使用JSON,XML,HTML和文本等多種格式發送和接收。儘管X在Ajax中表明XML, 但因爲JSON的許多優點,更加輕量以及是Javascript的一部分,目前JSON的使用比XML更加廣泛。瀏覽器
JSON(JavaScript Object Notation) 是一種輕級的數據交換格式。JSON其實是JavaScript的一個子集。可是和JavaScript的語法稍微有些不一樣,有屬於JSON本身的語法。安全
JSON構建於兩種形式:服務器
在JSON中值支持如下幾種數據類型:cookie
在JavaScript中,能夠直接使用JSON,JavaScript內置了JSON的解析。
JSON 對象
JSON對象定義在全局,該對象包含了兩個方法,除了這兩個方法, JSON這個對象自己並無其餘做用,也不能被調用或者做爲構造函數調用。
JSON.stringify()
將 JavaScript 中的對象或數組序列化成JSON字符串。簡單來講 JSON 是 JavaScript 對象的字符串表示法,它使用文本表示一個 JS 對象的信息,本質是一個字符串。
序列化將對象的狀態信息轉換爲能夠存儲或傳輸的形式的過程。
例如在 JavaScript 中定義的對象:
let obj = {a:1,b:2}
此對象存在於內存中,並不能將期結構存儲在cookie或localStorage或傳遞給後端。而此時就須要調用此方法序列換爲一個 JSON 字符串。
console.log(JSON.stringify(obj)); // {"a":1,"b":2}
JSON.parse()
將 JSON 字符串反序列化成 JavaScript 中的對象或數組。JSON 字符串自己只是一個字符串,不能經過屬性名的方式獲取對應的值。要轉換爲對象就可使用 key 來取值。
反序列化將能夠存儲或傳輸的形式轉換爲對象的過程。
例如從後端拿到一個 JSON 字符串 :
let objStr = '{"a":1,"b":2}'
此時不能使用 objStr.a 取到數值1,由於 objStr 自己只是一個字符串值,並非對象。
須要把JSON 字符串轉成可用的對象:
console.log(JSON.parse(objStr)); // {"a":1,"b":2}
Ajax 中的Asynchronous 是異步的意思,結合 Ajax 能夠和服務器進行通訊,能夠說Ajax是用JavaScript執行異步的網絡請求。
所謂的異步就是,一個異步過程調用發出後,調用者不會馬上獲得結果。而是在 調用 發出後,被調用者經過狀態、通知來通知調用者,或經過回調函數處理這個調用。
其中DOM事件,定時器就是典型的異步操做。拿定時器舉例,當調用 setTimeout 函數時候,就發起了一個異步操做,此時不會立馬獲得反饋,而到了設置的時間,會調用傳入的回調函數,一旦回調函數執行就獲得通知說明異步完成了。
setTimeout(function(){ console.log('執行此回調函數,異步完成獲得通知,該幹嗎幹嗎!!!'); }, 1000)
與之對應的還有一個同步的概念,所謂同步,就是在發出一個調用時,在沒有獲得結果以前,該調用就不返回。可是一旦調用返回,就獲得返回值了。由調用者主動等待這個調用的結果。
好比拿一個 JavaScript 中函數調用舉例:
var arr = [1,2,3,4,5,6,7,8]; arr.map((item) => { return item * 2 }) arr.forEach((item) => { return item * 2 })
上述代碼中只有 map 指向以後,獲得告終果,才能繼續調用 forEach, 這是一個同步調用的過程。
在使用 Ajax 時候,發出的是一個異步請求,要經過調用函數得到響應。
使用 JavaScript 建立一個請求對象實例,調用該實例下的方法,設置好請求的URL地址和請求數據,發送異步請求。發送後等待服務端響應,響應是以觸發事件來通知,隨後經過請求對象實例拿到HTTP狀態以及響應的內容。
完成一次請求,代碼示意以下所示
let xhr = new XMLHttpRequest; console.log(xhr.readyState); // 0 UNSENT 建立實例對象,還沒有調用open(); xhr.open('GET','http://kuapi.wykiss.cn/api?json=true',true); console.log(xhr.readyState); // 1 OPENED open()方法已成功調用。 // 當readyState狀態發生變化時,觸發此事件 xhr.onreadystatechange = function () { console.log(xhr.readyState); if(xhr.readyState === 2){ // 2 HEADERS_RECEIVED 能夠獲取到響應頭信息 console.log('響應頭信息爲:',xhr.getAllResponseHeaders()) }else if(xhr.readyState === 3){ // 3 LOADING 正在接收部分響應內容 console.log('接收的部份內容是:',xhr.response) }else if(xhr.readyState === 4) { // 4 DONE 請求操做已經完成,響應的內容所有接受完成 console.log('接收所有內容是:',xhr.response) } } // 請求操做完成 觸發的事件 xhr.onload = function () { console.log('請求操做完成,觸發此事件') console.log('能夠直接獲取響應的所有內容',xhr.response) } xhr.send();
咋眼一看,內容還挺多,分解每個知識點以下。
XMLHttpRequest 是規範制定的API,已經被現代瀏覽器普遍使用,它爲客戶端提供了在客戶端和服務器之間傳輸數據的功能,是Ajax技術的核心所在。
全局會提供一個 XMLHttpRequest 構造函數來初始化一個請求實例對象。
var xhr = new XMLHttpRequest();
此對象上會有多個屬性和方法。
只讀屬性,xhr.readyState 記錄了請求實例對象運行過程當中所處的狀態,使用數字來表示。如下是每一個數字表明的含義:
值 | 狀態 | 描述 |
---|---|---|
0 | UNSENT | 請求對象已建立,還沒有調用 open()方法 |
1 | OPENED | open()方法已成功調用 |
2 | HEADERS_RECEIVED | send() 方法已調用,能夠獲取到響應頭信息 |
3 | LOADING | 正在接收部分響應內容 |
4 | DONE | 請求操做已經完成,響應的內容所有接受完成 |
兩個都是隻讀屬性,存的是服務器的響應內容。 responseText表示服務器響應內容的文本形式。
可讀可寫屬性,xhr.responseType 表示響應的類型, 缺省爲空字符串, 可取 "arraybuffer" , "blob" , "document" , "json" , and "text" 共五種類型。
當將responseType設置爲一個特定的類型時,你須要確保服務器所返回的類型和你所設置的返回值類型是兼容的。那麼若是二者類型不兼容,服務器返回的數據變成了null,即便服務器返回了數據。還有一個要注意的是,給一個同步請求設置responseType會拋出一個InvalidAccessError 的異常。
xhr.responseURL 返回ajax請求最終的URL, 若是請求中存在重定向, 那麼responseURL表示重定向以後的URL。
只讀屬性。xhr.status存的是數字狀態碼,是標準的HTTML狀態碼。在請求完成前,status的值爲0。若是請求出錯,瀏覽器返回的 status 也爲0。若是服務器響應中沒有明確指定status碼, status碼將會默認爲200。
只讀屬性。xhr.status存的是服務器返回的狀態短語。這個屬性包含了返回狀態對應的文本信息,例如"OK"或是"Not Found"。
xhr.open() 方法初始化一個請求。
語法:
xhr.open(method, url)
xhr.open(method, url, async)
接下來討論的是在瀏覽器應用層面中GET和POST發送數據的不一樣。
- GET產生的URL地址能夠被Bookmark,而POST不能夠。 - GET請求只能進行url編碼,而POST支持多種編碼方式。 - GET請求參數會被完整保留在瀏覽器歷史記錄裏,而POST中的參數不會被保留。 - GET請求在URL中傳送的參數是有長度限制的,而POST麼有。 - GET比POST更不安全,由於參數直接暴露在URL上,因此不能用來傳遞敏感信息。 - GET參數經過URL傳遞,POST放在Request body中。
http://kuapi.wykiss.cn/api?js...
async 可選參數。默認爲true,表示執行是否是執行異步操做。true,爲異步,false,爲同步。當設置false時,瀏覽器會出現一個警告。
// Ajax 發出異步請求 // ..... 代碼省略 console.log('沒獲得結果,我先執行');
// Ajax 發出同步請求 // ..... 代碼省略 console.log('只有同步操做完成後,我才能執行');
xhr.send() 方法用於發送 HTTP 請求。若是是異步請求(默認爲異步請求),則此方法會在請求發送後當即返回,接着繼續執行send後面的代碼;若是是同步請求,則此方法直到服務端響應結束後所有拿到響應的數據後纔會返回。
xhr.send() 方法接受一個可選的參數,其做爲請求主體,發送 post 時會用到;若是請求方法是 GET,則應將請求主體設置爲 null。
注意:請求方法爲 post 時,要在請求頭(headers)中的 Content-Type 設置消息主體編碼方式,這樣服務端一般是根據請求頭(headers)中的 Content-Type 字段來獲知請求中的消息主體是用何種方式編碼,再對主體進行解析。
Content-Type 被指定爲 application/x-www-form-urlencoded;提交的數據按照 key1=val1&key2=val2 的方式進行編碼,key 和 val 都進行了 URL 轉碼。大部分服務端語言都對這種方式有很好的支持。例如 PHP 中,$_ POST[' json '] 能夠獲取到 true 的值,$_POST['country'] 能夠獲得 中國 值。
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); xhr.send('json=true&country=中國');
關於URL編碼
在ajax請求操做完成後觸發, 觸發時機在 readyState==4 狀態以後,這時候返回的內容已所有接受。
xhr.onload = function(){ var s = xhr.status; if((s >= 200 && s < 300) || s == 304){ var resp = xhr.responseText; //TODO ... } }
在readystate記錄的狀態改變時觸發。onreadystatechange 方法會被觸發4次。一般在事件處理函數中判斷 readystate 爲4的狀況下,纔算所有接受到內容。
xhr.onreadystatechange = function(e){ if(xhr.readyState==4){ var s = xhr.status; if((s >= 200 && s < 300) || s == 304){ var resp = xhr.responseText; //TODO ... } } }
以上是對Ajax知識點的總結,若有問題,歡迎指正!
擴展閱讀:
https://xhr.spec.whatwg.org/#states
http://www.ruanyifeng.com/blog/2010/02/url_encoding.html
https://imququ.com/post/four-ways-to-post-data-in-http.html