Ajax-運行原理及其實現步驟、服務端響應的數據格式、獲取服務端響應(狀態碼)、Ajax 封裝

傳統網站中存在的問題

  • 網速慢的情況下,頁面加載時間長,用戶只能等待
  • 表單提交後,如果一項內容不合格,需要重新填寫所有表單內容
  • 頁面跳轉,重新加載頁面,造成資源浪費,增加用戶等待時間
Ajax :它是瀏覽器提供的一套方法,可以實現頁面無刷新更新數據,提高用戶瀏覽網站應用的體驗。

Ajax 運行原理及實現

Ajax 運行原理
Ajax 相當於瀏覽器發送請求與接收響應的代理人,以實現在不影響用戶瀏覽頁面的情況下,局部更新頁面數據,從而提高用戶體驗。
在這裏插入圖片描述
Ajax的實現步驟

<script type="text/javascript">
//1、創建ajax對象
const xhr=new XMLHttpRequest();
//2、添加請求方式
xhr.open('get','http://localhost:3000/first')
//3、發送請求
xhr.send();
//4、接收服務端返回給客戶端的結果
//接收完響應自動觸發事件
xhr.onload=function(){
   //xhr.responseText獲取服務端的響應數據
   console.log(xhr.responseText);
   
}
</script>

//服務端
app.get('/first',(req,res)=>{
    res.send('我響應了ajax的請求')
})

服務端響應的數據格式

在 http 請求與響應的過程中,無論是請求參數還是響應內容,
如果是對象類型,最終都會被轉換爲對象字符串進行傳輸。
JSON.parse() // 將 json 字符串轉換爲json對象

請求參數傳遞

傳統網站表單提交
 <form method="get" action="http://www.example.com">
     <input type="text" name="username"/>
     <input type="password" name="password">
 </form>
 <!– http://www.example.com?username=zhangsan&password=123456 -->

Ajax傳遞方式

GET    請求方式
xhr.open('get', 'http://www.example.com?name=zhangsan&age=20');
//get請求方式將請求的參數放在url後面

POST 請求方式
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') xhr.send('name=zhangsan&age=20');
//post請求方式把請求的參數放置在請求體中進行傳遞

請求報文

在 HTTP 請求和響應的過程中傳遞的數據塊就叫報文,包括要傳送的數據和一些附加信息,這些數據和信息要遵守規定好的格式。

請求參數的格式


1、application/x-www-form-urlencoded
 name=zhangsan&age=20&sex=2、application/json
  {name: 'zhangsan', age: '20', sex: '男'}
  // 在請求頭中指定 Content-Type 屬性的值是 application/json,告訴服務器端當前請求參數的格式是 json
     JSON.stringify() // 將json對象轉換爲json字符串
     
  注意:get 請求是不能提交 json 對象數據格式的,傳統網站的表單提交也是不支持 json 對象數據格式的。

獲取服務器端的響應

Ajax 狀態碼

在創建ajax對象,配置ajax對象,發送請求,以及接收完服務器端響應數據,這個過程中的每一個步驟都會對應一個數值,這個數值就是ajax狀態碼。

0:請求未初始化(還沒有調用open())
1:請求已經建立,但是還沒有發送(還沒有調用send())
2:請求已經發送
3:請求正在處理中,通常響應中已經有部分數據可以用了
4:響應已經完成,可以獲取並使用服務器的響應了

xhr.readyState // 獲取Ajax 狀態碼

onreadystatechange 事件
當 Ajax 狀態碼發生變化時將自動觸發該事件

在事件處理函數中可以獲取 Ajax 狀態碼並對其進行判斷,當狀態碼爲 4 時就可以通過 xhr.responseText 獲取服務器端的響應數據了.

 // 當Ajax狀態碼發生變化時
 xhr.onreadystatechange = function () {
     // 判斷當Ajax狀態碼爲4時
     if (xhr.readyState == 4) {
         // 獲取服務器端的響應數據
         console.log(xhr.responseText);
     }
 }
 
 //推薦使用onload事件、不需要兼容、不需要判斷ajax狀態碼、不被調用多次

Ajax 錯誤處理

1. 網絡暢通,服務器端能接收到請求,服務器端返回的結果不是預期結果。

可以判斷服務器端返回的狀態碼,分別進行處理。xhr.status 獲取http狀態碼

2. 網絡暢通,服務器端沒有接收到請求,返回404狀態碼。

檢查請求地址是否錯誤。

3. 網絡暢通,服務器端能接收到請求,服務器端返回500狀態碼。

服務器端錯誤,

4. 網絡中斷,請求無法發送到服務器端。

會觸發xhr對象下面的onerror事件,在onerror事件處理函數中對錯誤進行處理

低版本 IE 瀏覽器的緩存問題

問題:在低版本的 IE 瀏覽器中,Ajax 請求有嚴重的緩存問題,即在請求地址不發生變化的情況下,
只有第一次請求會真正發送到服務器端,後續的請求都會從瀏覽器的緩存中獲取結果。
即使服務器端的數據更新了,客戶端依然拿到的是緩存中的舊數據。

解決方案:在請求地址的後面加請求參數,保證每一次請求中的請求參數的值不相同。
xhr.open('get', 'http://www.example.com?t=' + Math.random());

Ajax 異步編程

同步異步概述

同步()
- 一個人同一時間只能做一件事情,只有一件事情做完,才能做另外一件事情。
- 落實到代碼中,就是上一行代碼執行完成後,才能執行下一行代碼,即代碼逐行執行
 console.log('before'); 
 console.log('after');

異步()
-個人一件事情做了一半,轉而去做其他事情,當其他事情做完以後,再回過頭來繼續做之前未完成的事情。
-落實到代碼上、就是異步代碼雖然需要花費時間去執行,但程序不會等待異步代碼執行完成後再繼續執行後續代碼,
-而是直接執行後續代碼,當後續代碼執行完成後再回頭看異步代碼是否返回結果,
-如果已有返回結果,再調用事先準備好的回調函數處理異步代碼執行的結果。

 console.log('before');
 setTimeout(
    () => { console.log('last');
 }, 2000);
 console.log('after');

Ajax 封裝
問題
發送一次請求代碼過多,發送多次請求代碼冗餘且重複
將請求代碼封裝到函數中,發請求時調用函數即可

<script>
    //ajax封裝
    function ajax(options) {
        //存儲默認值
        var defaults={
            type:'get',
            url:'',
            data:{},
            header:{
                'Content-Type':'application/x-www-form-urlencoded'
            },
            success:function(){},
            error:function(){}
        }
        //使用options覆蓋defaults
        Object.assign(defaults,options);
        //創建ajax對象
        var xhr = new XMLHttpRequest();

        //設置拼接請求參數變量
        var params = '';
        for (attr in defaults.data) {
            //拼接參數、爲字符串格式
            params += attr + '=' + defaults.data[attr] + '&';
        }
        //將參數最後面的&符號截取掉、並重新賦值
        params = params.substr(0, params.length - 1)

        //判斷請求方式  
        if (defaults.type == 'get') {
            //如果請求參數是get就拼接到參數的請求路徑後面
            defaults.url = defaults.url + "?" + params;
        }

        //配置ajax
        xhr.open(defaults.type, defaults.url);
        //如果請求參數爲post
        if (defaults.type == 'post') {
            //用戶希望向服務器端傳遞的請求參數的類型
            var contentType = defaults.header['Content-Type']
            //明確post的請求類型
            xhr.setRequestHeader('Content-Type', contentType);
            
            if (contentType == 'application/json') {
                //是post參數直接放在請求體中
                xhr.send(JSON.stringify(defaults.data));
            } else {
                 //發送請求
                //向服務器端傳遞普通類型的請求參數
            xhr.send(params);
        }
     }else{
         //發送請求
         xhr.send();
     }
 
        //接收完響應數據後觸發
        xhr.onload = function () {
            //獲取響應頭中的數據
         var contentType=  xhr.getResponseHeader('Content-Type');
         //服務器端返回的數據
         var responseText=xhr.responseText;
         //判斷字符串是否包含某一個字符
            if(contentType.includes('application/json')){
                responseText=JSON.parse(responseText)
            }

            if(xhr.status==200){
           //調用請求成功的函數
            defaults.success(responseText,xhr);    
            }else{
            //獲取調用失敗的函數
            defaults.error(responseText,xhr)
         }
    }
  }

  
  
  
    ajax({
          
        // type:"post",
        //請求地址
        url: 'http://localhost:3000/responseData',
        //回調函數、返回響應信息
        success: function (data) {
            console.log('這裏是success函數');
                         console.log(data);
                         
        } 
    
    })


//服務器的路由
app.get('/responseData',(req,res)=>{
    
    res.send({"name":"zs" });
})
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章