Ajax 知識點的那些事

Ajax是什麼

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

JSON(JavaScript Object Notation) 是一種輕級的數據交換格式。JSON其實是JavaScript的一個子集。可是和JavaScript的語法稍微有些不一樣,有屬於JSON本身的語法。安全

JSON構建於兩種形式:服務器

  1. 無序的「‘名稱/值’對」集合
    一個對象以「{」(左括號)開始,「}」(右括號)結束。每一個「名稱」後跟一個「:」(冒號);「‘名稱/值’ 對」之間使用「,」(逗號)分隔。
  2. 值的有序列表
    一個數組以「[」(左中括號)開始,「]」(右中括號)結束。值之間使用「,」(逗號)分隔。

在JSON中值支持如下幾種數據類型:cookie

  • number:和JavaScript的number徹底一致,在JSON中數字不能以0開頭。
  • boolean:JavaScript的true或false;
  • string:JavaScript的string;
  • null:JavaScript的null;
  • array:JavaScript的Array表示方式——[];在JSON中結尾不能有逗號。
  • object:JavaScript的{ ... }表示方式。在JSON中結尾不能有逗號,key值必須加上雙引號。

在JavaScript中,能夠直接使用JSON,JavaScript內置了JSON的解析。

JSON 對象

JSON對象定義在全局,該對象包含了兩個方法,除了這兩個方法, JSON這個對象自己並無其餘做用,也不能被調用或者做爲構造函數調用。

JSON.stringify()

JavaScript 中的對象或數組序列化成JSON字符串。簡單來講 JSONJavaScript 對象的字符串表示法,它使用文本表示一個 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 時候,發出的是一個異步請求,要經過調用函數得到響應。

分解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 對象

XMLHttpRequest 是規範制定的API,已經被現代瀏覽器普遍使用,它爲客戶端提供了在客戶端和服務器之間傳輸數據的功能,是Ajax技術的核心所在。

全局會提供一個 XMLHttpRequest 構造函數來初始化一個請求實例對象。

var xhr = new XMLHttpRequest();

此對象上會有多個屬性和方法。

圖片描述

readyState 屬性

只讀屬性,xhr.readyState 記錄了請求實例對象運行過程當中所處的狀態,使用數字來表示。如下是每一個數字表明的含義:

狀態 描述
0 UNSENT 請求對象已建立,還沒有調用 open()方法
1 OPENED open()方法已成功調用
2 HEADERS_RECEIVED send() 方法已調用,能夠獲取到響應頭信息
3 LOADING 正在接收部分響應內容
4 DONE 請求操做已經完成,響應的內容所有接受完成

response 和responseText 屬性

兩個都是隻讀屬性,存的是服務器的響應內容。 responseText表示服務器響應內容的文本形式。

responseType 屬性

可讀可寫屬性,xhr.responseType 表示響應的類型, 缺省爲空字符串, 可取 "arraybuffer" , "blob" , "document" , "json" , and "text" 共五種類型。
當將responseType設置爲一個特定的類型時,你須要確保服務器所返回的類型和你所設置的返回值類型是兼容的。那麼若是二者類型不兼容,服務器返回的數據變成了null,即便服務器返回了數據。還有一個要注意的是,給一個同步請求設置responseType會拋出一個InvalidAccessError 的異常。

responseURL 屬性

xhr.responseURL 返回ajax請求最終的URL, 若是請求中存在重定向, 那麼responseURL表示重定向以後的URL。

status 屬性

只讀屬性。xhr.status存的是數字狀態碼,是標準的HTTML狀態碼。在請求完成前,status的值爲0。若是請求出錯,瀏覽器返回的 status 也爲0。若是服務器響應中沒有明確指定status碼, status碼將會默認爲200。

statusText 屬性

只讀屬性。xhr.status存的是服務器返回的狀態短語。這個屬性包含了返回狀態對應的文本信息,例如"OK"或是"Not Found"。

open() 方法

xhr.open() 方法初始化一個請求。

語法:

xhr.open(method, url)
xhr.open(method, url, async)
  • method 要使用的HTTP方法,好比 「GET」、「POST」、「PUT」、「DELETE」等。經常使用的是「GET」、「POST」請求方式。其餘的方法後端須要特別的支持。

接下來討論的是在瀏覽器應用層面中GET和POST發送數據的不一樣。

- GET產生的URL地址能夠被Bookmark,而POST不能夠。
- GET請求只能進行url編碼,而POST支持多種編碼方式。
- GET請求參數會被完整保留在瀏覽器歷史記錄裏,而POST中的參數不會被保留。
- GET請求在URL中傳送的參數是有長度限制的,而POST麼有。
- GET比POST更不安全,由於參數直接暴露在URL上,因此不能用來傳遞敏感信息。
- GET參數經過URL傳遞,POST放在Request body中。
  • url 發送請求的URL地址。若是發送的是 get 請求要把數據寫在地址欄的後面發送給後端。例如:
http://kuapi.wykiss.cn/api?js...
  • async 可選參數。默認爲true,表示執行是否是執行異步操做。true,爲異步,false,爲同步。當設置false時,瀏覽器會出現一個警告。

    • 異步請求發出後,調用者不會馬上獲得結果。而是在 調用 發出後,被調用者經過觸發事件,調用事件處理回調函數。在沒有獲得後端返回的結果以前,異步操做以後的代碼會繼續執行。
    // Ajax 發出異步請求
    // ..... 代碼省略
    console.log('沒獲得結果,我先執行');
    • 同步請求發出後,在沒有獲得結果以前,該調用就不返回。這就意味着,後續的代碼不能被執行,只有等到同步調用結束後獲得告終果,才能繼續執行代碼。
    // Ajax 發出同步請求
    // ..... 代碼省略
    console.log('只有同步操做完成後,我才能執行');

send() 方法

xhr.send() 方法用於發送 HTTP 請求。若是是異步請求(默認爲異步請求),則此方法會在請求發送後當即返回,接着繼續執行send後面的代碼;若是是同步請求,則此方法直到服務端響應結束後所有拿到響應的數據後纔會返回。

xhr.send() 方法接受一個可選的參數,其做爲請求主體,發送 post 時會用到;若是請求方法是 GET,則應將請求主體設置爲 null。

注意:請求方法爲 post 時,要在請求頭(headers)中的 Content-Type 設置消息主體編碼方式,這樣服務端一般是根據請求頭(headers)中的 Content-Type 字段來獲知請求中的消息主體是用何種方式編碼,再對主體進行解析。

  • application/x-www-form-urlencoded

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編碼

    • URL編碼是一種瀏覽器用來打包表單輸入的格式,瀏覽器從表單中獲取全部的name和其對應的value,將他們以name/value編碼方式做爲URL的一部分或者分離的發送到服務器上。在 ajax 中要手動設置 Content-Type 爲 application/x-www-form-urlencoded。
    • URL編碼規則:每對name/value由&分開,每對來自表單的name/value用=分開。若是用戶沒有輸入值的那個name依舊會出現不過就是沒有值。URL編碼是在字符ASCII碼的十六進制數的前面加上%。例如:中國 被轉成了 %E4%B8%AD%E5%9B%BD

onload 事件

在ajax請求操做完成後觸發, 觸發時機在 readyState==4 狀態以後,這時候返回的內容已所有接受。

xhr.onload = function(){
  var s = xhr.status;
  if((s >= 200 && s < 300) || s == 304){
    var resp = xhr.responseText;
    //TODO ...
  }
}

onreadystatechange 事件

在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知識點的總結,若有問題,歡迎指正!

擴展閱讀:

  • readyState狀態描述
https://xhr.spec.whatwg.org/#states
  • 關於URL編碼
http://www.ruanyifeng.com/blog/2010/02/url_encoding.html
  • 四種常見的 POST 提交數據方式:
https://imququ.com/post/four-ways-to-post-data-in-http.html
相關文章
相關標籤/搜索