開發與維運

web前端javaScript 之 【Ajax】

Ajax是幹什麼的,為什麼要學這個技術:

我們在上網瀏覽網站的時候,經常會看到下拉加載的的功能。例如百度圖片、淘寶列表等等……,這種我們每次下滑,就自動加載更多的信息。這種信息不用每次刷新頁面,而就會自動加載出來;那麼我們前端,像這種不必刷新頁面也能獲取新的數據的技術,我們就需要使用ajax來實現。而ajax也是目前Web開發人員必須要掌握一種技術。簡單來講,ajax就是提交併且接收了服務器的數據,從而可以獲取新的數據,來渲染頁面的更新

Ajax技術核心是XMLHttpRequest對象(簡稱XHR),幫助記憶,可以想象是“小黃人”的拼音簡稱。這是由微軟首先引入的一個特性,其他瀏覽器提供商也都是後來慢慢相同的實現這個技術。也是在2005年低,2006年初,Ajax技術才慢慢的紅遍了技術圈。IE5是第一款引入的XHR對象的瀏覽器,目前我們只講解適合於IE7之後的版本,之前的不做講解。

---用法:---

一、創建一個ajax對象

首先我們需要構造出一個新的XMLHttpRequest

var xhr = new XMLHttpRequest()

二、配置這個對象open(發送方式, 地址, 是否異步);

構造完之後,我們需要創建一個請求發送我們的數據,因為向服務器發送了請求,我們才能得到想要的數據。創建我們需要一個固定的方法open()

open()它有三個參數,第一個是請求的方式五種方式 :get/post/put/delete/head),第二個是請求的地址URL,第三個是個布爾值true/false代表是否異步

比如我們向一個後端接口/villin.php發一個get請求,大部分的請求都是異步加載,我們我們就可以這樣寫。

var xhr = new XMLHttpRequest();
xhr.open('get', './villin.php', true);

三、發送請求

這就創造出了一個簡單的請求數據,那麼接下來我們要把這個數據發送給數據庫,方法send(null)

var xhr = new XMLHttpRequest();
xhr.open('get', './villin.php', true);
xhr.send(null)

send()方法按照中文意思理解,就是發送,它接收一個參數,作為請求主體發送的數據。如果不需要通過請求主體發送數據,就傳入一個null,也可以不傳,但是對於某些瀏覽器來說,是必須要傳的,所以我們規範一點,寫上null。

四、監聽響應

這時,後端服務器接收到了我們發送的數據,就會返回我們想要的數據。

XHR的技術價值就是可以實時監聽數據的變化,實時返回新的數據,那麼怎麼監聽?他自身攜帶了一個屬性,叫onreadystatechange,從字面意思理解,就是實時監聽改變。所以我們監聽之後要做的事件,都需要寫在onreadystatechange函數當中。

onreadystatechange會監聽一個叫readyState的值,這個值很重要,它會反映出當前響應過程的活動階段,用0~4來表示:

0表示XHR剛創建出來,還沒有初始化,沒調用open()
1表示已經調用open()方法,但還沒有調用send()
2表示已經調用send()方法,但還沒有接收到數據。
3表示服務器已經接收到了部分響應數據。
4表示服務器已經接收到了全部響應數據,可以在客戶端使用了。

所以當readyState返回4的時候,說明數據返回成功,我們就可以拿到相應的數據了。

    var xhr = new XMLHttpRequest();
    xhr.open('get', './villin.php', true);
    xhr.onreadystatechange = function () {

        if (this.readyState !== 4) {
            return;
        }else{   
            //成功返回數據,在這裡獲取數據
        }
    }
    xhr.send(null) // 要成功發送請求頭信息,onreadystatechange一定要在open()之後,send()之前監聽。

此時說明服務器已經接收到了全部響應(但響應未必是返回成功的數據)。那麼服務器會把響應數據返回給瀏覽器,瀏覽器也就返回相應的狀態碼status,表示數據異常或成功。常見的狀態碼如下:

2開頭,代表響應成功,如200
3開頭,代表重定向,如302頁面暫時重定向,304表示請求的資源並沒有被修改,可以使用瀏覽器中緩存的版本。
4開頭,請求有錯誤,如400
5開頭,服務器報錯,如500

所以我們要使用返回來的數據,先判斷是否返回正常,一般是>=200並且<300。返回成功後,數據會被放置在一個叫responseText當中,我們直接打印出responseText就可以提取出內部的文本。

    var xhr = new XMLHttpRequest();
    xhr.open('get', './villin.php', true);
    xhr.onreadystatechange = function () {

        if (this.readyState !== 4) {
            return;
        }else{   
            //成功返回數據,在這裡獲取數據
            if(this.status >= 200 && this.status < 300) {
              console.log('請求成功')
              console.log(this.responseText)  // 此刻拿到後端的數據,打印出responseText
            }else{
              console.log('請求出錯')
            }
        }
    }
    xhr.send(null) // 要成功發送請求頭信息,onreadystatechange一定要在open()之後,send()之前監聽。

---超時設定:timeout---

最初,IE8為XHR提供了超時屬性timeout,表示請求在等待多少毫秒之後就終止。再給timeout設置超時設定後,在規定時間沒有接收到請求,那麼就會觸發timeout,進而調用ontimeout程序,如下:

    var xhr = new XMLHttpRequest();
    xhr.open('get', './villin.php', true);
    xhr.onreadystatechange = function () {

        if (this.readyState !== 4) {
            return;
        }else{
          try{
              //成功返回數據,在這裡獲取數據
              if(this.status >= 200 && this.status < 300) {
                  console.log('請求成功')
                  console.log(this.responseText)  // 此刻拿到後端的數據,打印出responseText
                }else{
                  console.log('請求出錯')
              }
          }catch(val){
              // 可以寫timeout處理程序
          }   
        }
    }
    xhr.timeout = 2000; // 設置超時時間為2000mm,超出會調用ontimeout事件
    xhr.ontimeout = function(){
      alert('請求超時2000mm')
    }
    xhr.send(null) // 要成功發送請求頭信息,onreadystatechange一定要在open()之後,send()之前監聽。

注意:如果在超時之後再訪問status就會出現錯誤,所以我們可以將判斷封裝到try...catch語句,這樣就可以完美的解決超時問題
雖然timeout是由IE提供的,不過目前其他瀏覽器的兼容性,還需要大家去嘗試。

---load事件---

Firefox在實現Ajax的簡化模型時,引入了load事件。它可以代替onreadystatechange事件,響應完畢後將觸發onload事件,所以我們就可以省去了檢查readyState屬性了,不比判斷readyState是否等於4的問題了。

    var xhr = new XMLHttpRequest();
    xhr.open('get', './villin.php', true);
    xhr.onload = function () {
      if(this.status >= 200 && this.status < 300) {
          console.log('請求成功')
          console.log(this.responseText)  // 此刻拿到後端的數據,打印出responseText
        }else{
          console.log('請求出錯')
      }
    }
    xhr.send(null)

目前Firefox、Oprea、Chrome、Safari都支持load事件。

---瀏覽器跨域---

通過XHR實現ajax通信的主要一個主要限制,就是來自跨域的安全策略(同源策略)。默認情況下,XHR對象只能訪問與包含它的頁面位於同一個域中的資源,這種安全策略是為了預防某些惡意行為。

怎麼解決跨域問題,其實IE與其他瀏覽器還各有千秋,比如IE與其他瀏覽器的CORS的實現,在open()方法中傳入對決URL地址,如www開頭的地址,我們就可以拿到絕對地址上的信息。還有一起其他跨域技術:

JSONP

Jsonp雖然和json長得很像,不過這兩個還是沒什麼關係的,json是以鍵和值的方式存在的一種格式,Jsonp是由回調函數和數據組成的一種技術。

Jsonp是通過動態<script>元素來使用的,使用的時候可以為src指定一個跨域的URL。<script>元素有能力不受限制的從其他域中加載資源,所以可以實現跨域請求。

<script src='www.avillin.com/?callback=handleaaa'></script> // URL就是此地址,後邊callback返回的就是函數,名稱為handleaaa
<script>
function handleaaa(response){
  console.log(response)
}
</script>

擴展:目前前端使用的vue框架中,也有自己的跨域方式,可以通過proxy來實現跨域。

更多關於ajax的知識,也歡迎一起探討。

本文作者:avillin

v-chat:villinWechat

Leave a Reply

Your email address will not be published. Required fields are marked *