Ajax知識點整理

1、javascript原生Ajax

1.簡介

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

  1. 能夠異步生成請求,用戶能夠在表單被處理時繼續與文檔交互。而傳統提交表單發送到服務器,用戶必須等待服務器處理數據並生成響應。
  2. 響應信息能夠僅更新頁面的一部分。而傳統提交表單到服務器後,整個頁面被刷新,全部上下文信息都丟失了。

XMLHttpRequest對象的特色:jquery

  1. XMLHttpRequest對象能夠接受任何數據類型而不只僅爲XML
  2. 它支持的協議類型包括不限於http(還包括file,ftp)

2.XMLHttpRequest的API

xhr.onreadystatechange

只要xhr.readyState的值改變一次,就會觸發一次readystatechange事件。因此能夠利用該事件來檢測readyState發生變化後的值。es6

readystatechange事件處理程序只能經過xhr.onreadystatechange(DOM0級法法)來綁定才能確保跨瀏覽器的兼容性,由於並不是全部瀏覽器都支持DOM2級方法ajax

xhr.readyState

請求/響應過程的當前活動階段。該屬性可能的值爲:json

  • 0:未初始化。還沒有調用open()方法。
  • 1: 啓動。已經調用open(),但還沒有調用send()。
  • 2: 發送。已經調用send(),但還沒有收到響應。
  • 3: 接收。已經接收到部分響應數據。
  • 4:完成。已經接收到所有響應數據,並且已經能夠在客戶端使用了。

xhr.status

響應的HTTP狀態碼。一般是將 200<= 狀態碼 <300 或 status爲304做爲響應成功的標誌。api

Tips: 304表示請求的資源並無被修改,能夠直接使用瀏覽器緩存中的版本,因此也意味着響應有效。跨域

xhr.statusText

HTTP狀態的說明文字。

xhr.responseText

做爲響應主體被返回的文本。

xhr.open()

初始化一個請求。

參數:

  • method:請求所使用的HTTP方法; 例如 "GET", "POST", "PUT", "DELETE"等

  • url:該請求要訪問的url。能夠是絕對地址,也能夠是相對於執行代碼的當前頁面的相對地址。

  • async:布爾值,是否異步發送請求,默認爲true

  • user(可選):用戶名,爲受權使用;默認爲空string.

  • password(可選):密碼,可選參數,爲受權使用;默認爲空string.

注意: 調用該方法並不會真正發送請求,只是啓動一個請求以備發送。

xhr.send()

發送請求. 若是該請求是異步模式(默認),該方法會馬上返回. 相反,若是請求是同步模式,則直到請求的響應徹底接受之後,該方法纔會返回.

參數:

  • 請求主體發送的數據。若是不須要請求主體發送數據,如GET請求,那麼必須傳入null,由於該參數對於有些瀏覽器是必需的。

xhr.abort()

若是請求已經被髮送,則馬上終止請求。

調用這個方法後,XHR對象會中止觸發事件readystatechange,也再也不容許訪問任何與響應有關的對象屬性。

xhr.setRequestHeader()

默認會發送的請求頭有:

  • Accept:瀏覽器可以處理的內容類型
  • Accept-Charset:瀏覽器可以顯示的字符集
  • Accept-Encoding:瀏覽器可以處理的壓縮編碼
  • Accept-language:瀏覽器當前設置的語言
  • Connection:瀏覽器與服務器之間鏈接的類型(一般爲keep-alive,即網絡鏈接就是持久的,使得對同一個服務器的請求能夠繼續在該鏈接上完成。)
  • Cookie:當前頁面設置的任何cookie
  • Host:發出請求的頁面所在的域
  • Referer:發出請求的頁面的URI. 即表示當前頁面是經過此來源頁面裏的連接進入的。服務端通常使用 Referer 首部識別訪問來源,可能會以此進行統計分析、日誌記錄以及緩存優化等。
  • User-Agent:瀏覽器用戶代理字符串

該方法會設置自定義的請求頭部信息。

參數:

  • header: 將要被賦值的請求頭名稱。
  • value: 給指定的請求頭賦的值。

xhr.getResponseHeader()

獲取相應響應頭字段的信息。

參數:

  • header:要獲取的響應頭的值的名稱

xhr.getAllResponseHeaders()

取得包含全部響應頭部信息的長字符串。

new FormData()

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設置值,這是它的方便之處。

3. 使用範例:GET請求

寫法步驟:

  1. 建立XMLHttpRequest對象:var xhr=new XMLHttpRequest()
  2. 指定xhr.onreadystatechange事件監聽函數,在函數中先檢測readyState屬性(表示請求/響應的階段)爲4(表完成),再檢測相應狀態(xhr.status>=200&&xhr.status<300)||xhr.status==304) ,再在頁面指定地方接受xhr.responseText(響應返回的文本)
  3. 執行xhr.open("GET",URL,是否異步)
  4. xhr.send(null)

實例:

<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);
  }

3. 使用範例:POST請求(發送json數據)

寫法步驟

  1. 處理提交按鈕默認行爲:若是提交按鈕button沒有設置type="button",那麼其默認type爲submit,要先調用e.preventDefault()取消按鈕提交表單的默認行爲。
  2. 準備好POST數據:經過DOM獲取表單數據,並將其轉換爲Object類型,再用JSON.stringify轉換爲json字符串。
  3. 建立XMLHttpRequest實例:var xhr=new XMLHttpRequest()
  4. 指定xhr.onreadystatechange事件處理函數:在函數中先檢測readyState屬性爲4,再檢測相應狀態(xhr.status>=200&&xhr.status<300)||xhr.status==304) ,再處理請求的響應文本xhr.responseText。若是獲得的響應文本也是json字符串,那麼也須要用JSON.parse方法將其從JSON字符串解析爲Object。
  5. xhr.open("POST",URL,是否異步)。
  6. 設置請求頭字段:xhr.setRequestHeader("Content-Type","application/json")設置請求頭段Content-Type爲application/json,告訴服務器在發送json數據。
  7. xhr.send(2.中準備好的json字符串)

實例:

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

4. 使用範例:POST請求(發送表單默認格式數據)

寫法步驟:

  1. 處理提交按鈕默認行爲:若是提交按鈕button沒有設置type="button",那麼其默認type爲submit,要先調用e.preventDefault()取消按鈕提交表單的默認行爲。
  2. 準備好POST數據:經過DOM獲取表單數據,並將其處理爲字符串"name1=value1&name2=value2...namen=valuen&"。
  3. 建立XMLHttpRequest實例:var xhr=new XMLHttpRequest()
  4. 指定xhr.onreadystatechange事件處理函數:在函數中先檢測readyState屬性爲4,再檢測相應狀態(xhr.status>=200&&xhr.status<300)||xhr.status==304) ,再處理請求的響應文本xhr.responseText。
  5. xhr.open("POST",URL,是否異步)。
  6. 設置請求頭字段:xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),告訴服務器在發送x-www-form-urlencoded數據。
  7. xhr.send(2.中準備好的字符串)。

實例:

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

5. 使用範例:POST請求(發送FormData數據)

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);

2、jQuery的$.ajax()

http://api.jquery.com/jQuery.ajax/

1. 簡介

執行Ajax請求。

2. 用例

(1)POST請求

$.ajax({
  method: 'POST',
  url:'example.php',
  data: {
    name: 'Bonnie',
    age: 26
  },
  dataType:'json'
}).done(function(msg){
  console.log(msg);
})

(2)請求的三種回調函數

$.ajax('example.php')
  .done(function(){
    alert('success');
  })
  .fail(function() {
    alert('error');
  })
  .always(function() {
    alert('complete')
  })

3.API

$.ajax(url[, settings])

url

請求的地址。

settings

這裏列出一些重點配置屬性:

contentType

default 'application/x-www-form-urlencoded; charset=UTF-8')

告訴服務器發送的數據類型。

crossDomain

default: false for same-domain requests, true for cross-domain requests)

是否跨域

data

Type: object or string or array)

要發送到服務器的數據。

dataType

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對其進行處理。

jqXHR.done(function(data, textStatus, jqXHR){})

請求成功的回調函數

jqXHR.fail(function(jqXHR, textStatus, errorThrown){})

請求錯誤的回調函數

jqXHR.always(funciton(ata | jqXHR,textStatus,jqXHR | errorThrown){})

請求成功和失敗都會執行的回調函數。

3、ES6的Fetch

1.簡介

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的一個示例。

fetch()方法

它返回一個 promise,這個promise會在請求響應後被resolve,並傳回Response對象。

當遇到網絡錯誤時,fetch()返回的promise會被reject,並傳回TypeError。

成功的fetch()檢查不只要包括promise被resolve,還要包括Response.ok屬性爲true.

fetch規範與jQuery.ajax()的不一樣:

  • 當接收到一個表明錯誤的 HTTP 狀態碼時,從 fetch()返回的 Promise 不會被標記爲 reject, 即便該 HTTP 響應的狀態碼是 404 或 500。相反,它會將 Promise 狀態標記爲 resolve (可是會將 resolve 的返回值的 ok 屬性設置爲 false ),僅當網絡故障時或請求被阻止時,纔會標記爲 reject。
  • 默認狀況下,fetch 不會從服務端發送或接收任何 cookies, 若是站點依賴於用戶 session,則會致使未經認證的請求。若是要發送 cookies,必須設置 credentials 選項

2.用例

(1)GET請求-獲取json數據

fetch(urlStr)
  .then( res => res.json()) //res是一個response對象,並非咱們指望的json結果。爲了獲取JSON內容,咱們須要使用 json()方法。res.json()方法返回的也是一個promise對象,因此須要再一次地使用then()
  .then( myJson => {
    console.log(myJson)
  })

(2)用例:POST請求-發送json數據

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))

3. API

(1) Body

Fetch API中的Body類表明Response/Request的body,容許你聲明其內容類型是什麼以及應該如何處理。

Body類由Response類和Request類實現,這爲對象response和request提供了一個相關聯的body(字節流)

屬性
Body.bodyUsed

只讀:包含一個指示body是否被讀取過的 Boolean 值。

方法
Body.json()

使用一個 JSON 對象來讀取 Response流中的數據,並將bodyUsed狀態改成已使用。

返回:一個promise, resolve的結果是Json 對象 而非字符串(即通過JSON.parse()解析過的JSON字符串)

Body.formdata()

使用一個 FormData 對象來讀取 Response流中的數據,並將bodyUsed狀態改成已使用。

返回: 一個 Promise,resolve的結果是FormData 對象。

Body.text()

使用一個USVString (文本) 對象來讀取 Response流中的數據,並將bodyUsed狀態改成已使用。

返回:一個包含USVString對象 (text)的Promise,resolve的結果的編碼爲UTF-8。

注意: 其與Body.json()方法的區別:一樣是請求json字符串文本:

  • 若是使用res.json(),那麼resolve的結果直接是JavaScript對象(或數組)
  • 若是使用res.text(),那麼resolve的結果是json字符串,須要使用JSON.parse()才能獲得JavaScript對象(或數組)
Body.arrayBuffer()

使用一個buffer數組來讀取 Response流中的數據,並將bodyUsed狀態改成已使用。

返回:A promise that resolves with an ArrayBuffer.

Body.blob()

使用一個Blob對象來讀取Response流中的數據,並將bodyUsed狀態改成已使用。

返回:A promise that resolves with a Blob.

(2)Headers

Headers 接口容許您對HTTP請求和響應頭執行各類操做。 這些操做包括檢索,設置,添加和刪除.

構造函數

let myHeader = new Headers()

append()

給現有的header添加一個值, 或者添加一個未存在的header並賦值.

delete()

從Headers對象中刪除指定header

Headers.get()

從Headers對象中返回指定header的第一個值.

(3)fetch方法的請求參數

{
    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
  }
method

請求的方法

headers

請求頭信息

mode

請求的模式:

  • no-cors(default):該模式容許來自 CDN 的腳本、其餘域的圖片和其餘一些跨域資源,但請求的 method 只能是HEAD、GET 或 POST。
  • same-origin:禁止跨域。若是一個請求是跨域的,那麼將返回一個 error,這樣確保全部的請求遵照同源策略。
  • cors:跨域請求。用來從第三方提供的 API 獲取數據。該模式遵照 CORS 協議,並只有有限的一些 Header 被暴露給 Response 對象,可是 body 是可讀的。
credentials

請求的憑據,如 omit、same-origin 或者 include。爲了在當前域名內自動發送 cookie , 必須提供這個選項。

redirect

可用的重定向模式: follow (自動重定向), error (若是產生重定向將自動終止而且拋出一個錯誤), 或者 manual (手動處理重定向).

referrer

能夠是 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

相關文章
相關標籤/搜索