JavaScript封裝屬於自己的Ajax並完善與拓展Ajax

現在所有主流的網站,基本上都用到了ajax技術,通過異步請求數據已經是一個很普及的實現方式。市面上主流的web前端框架也都有自己封裝的ajax,而且都是大同小異的。也就是說,Ajax這個輪子已經是多的不能再多了,那爲什麼我們還要自己封裝一個Ajax呢?

想要了解一個技術或者某個功能的實現原理,只有動手實踐才能真正的瞭解。就如我在csdn上第一篇博客的博文描述。探索技術的路上本應該自己造輪子,即使市面上有再多的選擇,自己動手嘗試也是必要的,第一次嘗試必然會問題衆多,但你不覺得解決他是一件很有成就感的事情嗎,這樣才能帶給你更大的進步和更深刻的領悟。

廢話不說,先來寫一個最基礎的ajax:

[javascript] view plain copy
print?
  1. function ajax(a){  
  2.     var ajax = new XMLHttpRequest();  
  3.     ajax.onreadystatechange = function(){  
  4.         if (ajax.readyState == 4 && ajax.status == 200) {  
  5.             a.success(JSON.stringify(ajax.responseText))  
  6.         }  
  7.     }  
  8.     ajax.open(a.method, a.url,true)  
  9.     ajax.send(a.data)  
  10. }  
  11.   
  12. ajax({  
  13.     method:’get’,  
  14.     url:’http://127.0.0.1:8081/test’,  
  15.     success:function(res){  
  16.         console.log(res)  
  17.     }  
  18. })  
  function ajax(a){
        var ajax = new XMLHttpRequest();
        ajax.onreadystatechange = function(){
            if (ajax.readyState == 4 && ajax.status == 200) {
                a.success(JSON.stringify(ajax.responseText))
            }
        }
        ajax.open(a.method, a.url,true)
        ajax.send(a.data)
    }

    ajax({
        method:'get',
        url:'http://127.0.0.1:8081/test',
        success:function(res){
            console.log(res)
        }
    })

一個ajax出爐了,通過調用、填寫參數即可請求到服務器。先來分析一下這個ajax的結構,可以看得出來,其實很簡單,只是new了一個XMLHttpRequest對象,然後通過onreadystatechange方法來處理返回值,現在我們只是做了一個判斷,當請求成功時就調用success方法,如果請求失敗,我們還沒有寫上去,後面我們慢慢完善這個ajax的邏輯。

然後調用ajax的open方法,open方法裏有三個參數,第一個是請求方式(如:get或post),第二個是請求的url地址,第三個是一個bool值,是否要異步請求。

最後使用send方法帶上參數發送請求即可。

這是,我的服務器已經收到一個請求,但他報了404錯誤,也就是找不到對應的頁面或路由,這時success方法也不會被調用執行。


那我們再來完善一下這個新生的ajax。我們只需要在onreadystatechange方法裏增加一個條件,當請求不成功時調用自身的error方法:

[javascript] view plain copy
print?
  1. ajax.onreadystatechange = function(){  
  2.     if (ajax.readyState == 4 && ajax.status == 200) {  
  3.         a.success(JSON.stringify(ajax.responseText))  
  4.     }else{  
  5.         a.error(ajax)  
  6.     }  
  7. }  
        ajax.onreadystatechange = function(){
            if (ajax.readyState == 4 && ajax.status == 200) {
                a.success(JSON.stringify(ajax.responseText))
            }else{
                a.error(ajax)
            }
        }

這樣我們就可以在ajax請求的時候加上error方法,當ajax請求失敗的時候執行我們想要執行的操作。現在我們拋除跨域請求的問題,當你發送post請求時,你會發現後臺接收不到傳過來的參數,調用如下:

[javascript] view plain copy
print?
  1. ajax({  
  2.     method:’get’,  
  3.     url:’http://localhost:8081/test’,  
  4.     data:’a=1’,  
  5.     success:function(res){  
  6.         console.log(res)  
  7.     },  
  8.     error:function(res){  
  9.         console.log(res)  
  10.     }  
  11. })  
   ajax({
        method:'get',
        url:'http://localhost:8081/test',
        data:'a=1',
        success:function(res){
            console.log(res)
        },
        error:function(res){
            console.log(res)
        }
    })

後端打印一下傳過來的參數,爲空。

出現這個問題的原因主要是請求頭沒有聲明,這時候我們需要初始化聲明一下請求頭,那我們加入一行代碼:

[javascript] view plain copy
print?
  1. ajax.setRequestHeader(“Content-type”“application/x-www-form-urlencoded”);  
     ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

設置Conten-type爲application/x-www-form-urlencoded,現在後端應該是已經可以收到參數了。那我們現在的ajax調用時實在太繁瑣,有些東西我們不想填的我們應該給他設置一個默認值,不然就會報錯。

比如error方法、method、還有是否異步的bool值等等。那我們再加入一些默認值,現在的ajax是這樣的:

[javascript] view plain copy
print?
  1. function ajax(a){  
  2.     a.method = a.method || ’get’;  
  3.     a.ajax = a.ajax || true;  
  4.     a.error = a.error || function(){  
  5.         console.warn(’Ajax請求失敗’);  
  6.     };  
  7.     var ajax = new XMLHttpRequest();  
  8.     ajax.onreadystatechange = function(){  
  9.         if (ajax.readyState == 4 && ajax.status == 200) {  
  10.             a.success(JSON.stringify(ajax.responseText))  
  11.         }else{  
  12.             a.error(ajax)  
  13.         }  
  14.     }  
  15.     ajax.open(a.method, a.url,a.ajax)  
  16.     ajax.setRequestHeader(”Content-type”“application/x-www-form-urlencoded”);  
  17.     ajax.send(a.data)  
  18. }  
  function ajax(a){
        a.method = a.method || 'get';
        a.ajax = a.ajax || true;
        a.error = a.error || function(){
            console.warn('Ajax請求失敗');
        };
        var ajax = new XMLHttpRequest();
        ajax.onreadystatechange = function(){
            if (ajax.readyState == 4 && ajax.status == 200) {
                a.success(JSON.stringify(ajax.responseText))
            }else{
                a.error(ajax)
            }
        }
        ajax.open(a.method, a.url,a.ajax)
        ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        ajax.send(a.data)
    }

現在的ajax還存在一個問題,在post請求的時候,如果我們要傳參,是需要通過字符串傳參的。那這種的書寫規則並不是很友好的:

[javascript] view plain copy
print?
  1. a=1&b=2  
a=1&b=2

而一般框架的傳參都是通過json的格式來輸入的,我們也不能偏離大衆習慣搞獨立,當然我們也要保留字符串的傳參方式,只是要擴展功能。

那我們需要加一個控制格式的參數,我們這裏用dataType這個參數來控制傳參格式,默認是字符串格式傳參好了,可以選擇json格式進行傳參即可。如果是json格式傳參,我們需要把json轉化成字符串類型,代碼如下:

[javascript] view plain copy
print?
  1. a.dataType = a.dataType || ‘string’;  
  2. var data = a.data;  
  3. if (a.dataType == ‘json’) {  
  4.     var nowData = “”;  
  5.     for (var i in data) {  
  6.         nowData += (nowData != ?‘&’:)+i+‘=’+data[i];  
  7.     }  
  8.     data = nowData;  
  9. }  
     a.dataType = a.dataType || 'string';
        var data = a.data;
        if (a.dataType == 'json') {
            var nowData = "";
            for (var i in data) {
                nowData += (nowData != ''?'&':'')+i+'='+data[i];
            }
            data = nowData;
        }

這樣,我們的ajax也就可以通過json格式進行傳參了。現在的ajax完整代碼和調用方式如下:

[javascript] view plain copy
print?
  1. function ajax(a){  
  2.     a.method = a.method || ’get’;  
  3.     a.ajax = a.ajax || true;  
  4.     a.dataType = a.dataType || ’string’;  
  5.     a.error = a.error || function(){  
  6.         console.warn(’Ajax請求失敗’);  
  7.     };  
  8.     var ajax = new XMLHttpRequest();  
  9.     ajax.onreadystatechange = function(){  
  10.         if (ajax.readyState == 4 && ajax.status == 200) {  
  11.             a.success(JSON.stringify(ajax.responseText))  
  12.         }else{  
  13.             a.error(ajax)  
  14.         }  
  15.     }  
  16.     var data = a.data;  
  17.     if (a.dataType == ‘json’) {  
  18.         var nowData = “”;  
  19.         for (var i in data) {  
  20.             nowData += (nowData != ?‘&’:)+i+‘=’+data[i];  
  21.         }  
  22.         data = nowData;  
  23.     }  
  24.     ajax.open(a.method, a.url,a.ajax)  
  25.     ajax.setRequestHeader(”Content-type”“application/x-www-form-urlencoded”);  
  26.     ajax.send(data)  
  27. }  
  28. //調用Ajax示例  
  29. ajax({  
  30.     method:’post’,  
  31.     url:’http://localhost:8081/test’,  
  32.     dataType:’json’,  
  33.     data:{  
  34.         a:’1’,  
  35.         b:’2’  
  36.     },  
  37.     success:function(res){  
  38.         console.log(res)  
  39.     }  
  40. })  
 function ajax(a){
        a.method = a.method || 'get';
        a.ajax = a.ajax || true;
        a.dataType = a.dataType || 'string';
        a.error = a.error || function(){
            console.warn('Ajax請求失敗');
        };
        var ajax = new XMLHttpRequest();
        ajax.onreadystatechange = function(){
            if (ajax.readyState == 4 && ajax.status == 200) {
                a.success(JSON.stringify(ajax.responseText))
            }else{
                a.error(ajax)
            }
        }
        var data = a.data;
        if (a.dataType == 'json') {
            var nowData = "";
            for (var i in data) {
                nowData += (nowData != ''?'&':'')+i+'='+data[i];
            }
            data = nowData;
        }
        ajax.open(a.method, a.url,a.ajax)
        ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        ajax.send(data)
    }
 //調用Ajax示例
    ajax({
        method:'post',
        url:'http://localhost:8081/test',
        dataType:'json',
        data:{
            a:'1',
            b:'2'
        },
        success:function(res){
            console.log(res)
        }
    })

現在這個Ajax基本上已經可以滿足業務上的所以需求,不過還有一點沒有實現,我們的Ajax不能設置請求頭?!爲了一些特殊需求的情況下,我們還是要把這一功能加上的:

[javascript] view plain copy
print?
  1. if (a.requestHeader) {  
  2.     for (var i in a.requestHeader) {  
  3.         ajax.setRequestHeader(i,a.requestHeader[i])  
  4.     }  
  5. }  
      if (a.requestHeader) {
            for (var i in a.requestHeader) {
                ajax.setRequestHeader(i,a.requestHeader[i])
            }
        }

現在的完整代碼入下:

[javascript] view plain copy
print?
  1. function ajax(a){  
  2.     a.method = a.method || ’get’;  
  3.     a.ajax = a.ajax || true;  
  4.     a.dataType = a.dataType || ’string’;  
  5.     a.error = a.error || function(){  
  6.         console.warn(’Ajax請求失敗’);  
  7.     };  
  8.     var ajax = new XMLHttpRequest();  
  9.     ajax.onreadystatechange = function(){  
  10.         if (ajax.readyState == 4 && ajax.status == 200) {  
  11.             a.success(JSON.parse(ajax.responseText))  
  12.         }else if (ajax.readyState != 4 && ajax.status != 200){  
  13.             a.error(ajax)  
  14.         }  
  15.     }  
  16.     var data = a.data;  
  17.     if (a.dataType == ‘json’) {  
  18.         var nowData = “”;  
  19.         for (var i in data) {  
  20.             nowData += (nowData != ?‘&’:)+i+‘=’+data[i];  
  21.         }  
  22.         data = nowData;  
  23.     }  
  24.     ajax.open(a.method, a.url,a.ajax)  
  25.     if (a.requestHeader) {  
  26.         for (var i in a.requestHeader) {  
  27.             ajax.setRequestHeader(i,a.requestHeader[i])  
  28.         }  
  29.     }  
  30.     ajax.setRequestHeader(”Content-type”“application/x-www-form-urlencoded”);  
  31.     ajax.send(data)  
  32. }  
  function ajax(a){
        a.method = a.method || 'get';
        a.ajax = a.ajax || true;
        a.dataType = a.dataType || 'string';
        a.error = a.error || function(){
            console.warn('Ajax請求失敗');
        };
        var ajax = new XMLHttpRequest();
        ajax.onreadystatechange = function(){
            if (ajax.readyState == 4 && ajax.status == 200) {
                a.success(JSON.parse(ajax.responseText))
            }else if (ajax.readyState != 4 && ajax.status != 200){
                a.error(ajax)
            }
        }
        var data = a.data;
        if (a.dataType == 'json') {
            var nowData = "";
            for (var i in data) {
                nowData += (nowData != ''?'&':'')+i+'='+data[i];
            }
            data = nowData;
        }
        ajax.open(a.method, a.url,a.ajax)
        if (a.requestHeader) {
            for (var i in a.requestHeader) {
                ajax.setRequestHeader(i,a.requestHeader[i])
            }
        }
        ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        ajax.send(data)
    }

完整示例代碼文件:JavaScript封裝Ajax完整示例代碼

相關技術小擴展:https://blog.csdn.net/superwebmaster/article/details/80665249




            </div>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章