據說每個大牛、小牛都應該有自己的庫——Ajax

謙行發表於2013-09-18

蹉跎到今天終於要寫Ajax部分了,平時工作中除了選擇器我用jQuery的最多的就是ajax,所以這部分在自己的框架中必不可少。

XMLHttpRequest

我以為對每個使用過Ajax的人來說XMLHttpRequest物件肯定是如雷貫耳,可是在和公司小夥伴兒的討論中我意識到,這個物件對有些已經使用Ajax很久的人來說仍然很陌生,jQuery等類庫把XMLHttpRequest物件封裝的太好了,以至於我們都不知道自己在使用它。關於JavaScript原生的Ajax之前寫過一篇Ajax初步理解的部落格,為了方便下面書寫,在這裡再介紹一下幾個重點概念。

Ajax的核心是JavaScript物件XmlHttpRequest,這個物件為向伺服器傳送請求和解析伺服器響應提供了流暢的介面。XmlHttpRequest可以使用JavaScript向伺服器提出請求並處理響應,而不阻塞使用者。該物件有兩個重要方法open與send

呼叫send()方法,請求被髮往伺服器,伺服器根據請求生成響應(Response),傳回給XHR物件,在收到響應後相應資料會填充到XHR物件的屬性,有四個相關屬性會被填充:

1. responseText:作為響應主體被返回的文字

2. responseXML:如果響應內容的型別是”text/xml”或”application/xml”,這個屬性將儲存包含著相應資料的XML文件

3. status:響應的HTTP狀態(200,404,500等)

4. statusText:HTTP狀態說明

XHR物件有一個readyState屬性,該屬性表示請求/響應過程中的當前活動階段,每當readyState值改變的時候都會觸發一次onreadystatechange事件。

瀏覽器相容的建立XHR物件方法

大家都懂得,IE總會製造些麻煩,看看瀏覽器相容的建立XHR物件方法,具體過程可以看看Ajax初步理解中的說明

function __createXHR(){
                var xhr = null;
                try {
                    // Firefox, Opera 8.0+, Safari,IE7+
                    xhr = new XMLHttpRequest();
                }
                catch (e) {
                    // Internet Explorer 
                    try {
                        xhr = new ActiveXObject("Msxml2.XMLHTTP");
                    }
                    catch (e) {
                        try {
                            xhr = new ActiveXObject("Microsoft.XMLHTTP");
                        }
                        catch (e) {
                            xhr = null;
                        }
                    }
                }
                return xhr;
            }

封裝

其實看看第一段關於XHR物件的說明就明白為什麼jQuery等類庫會對XHR做如此徹底的封裝了,這個物件實在是太複雜了,引數的設定都要有時機問題,所以我也走上了封裝之路。

ajax: function(configs) { 
                    var settings = { 
                        "url": "",  //請求地址
                        "method": "post", //請求使用方法
                        "user": "", //使用者名稱
                        "password": "", //密碼
                        "data": null, //引數(text/json)
                        "responseType": "text", //返回值獲取方式 text/xml 
                        "headers": {}, //自定義的HttpHeader
                        "enableCache":true, //是否使用快取
                        "onSucceed": null, //成功控制程式碼
                        "onClientError": null, //客戶端錯誤控制程式碼
                        "onServerError": null //伺服器端錯誤控制程式碼
                    }; 
                    for (s in settings) { 
                        settings[s] = configs[s] ? configs[s] : settings[s];  //應用自定義配置
                    } 
                    var xhr = _createXHR();  //建立XHR物件
                    xhr.onreadystatechange = function() { 
                        if (xhr.readyState == 4) {  //請求完成,響應就緒
                            var result = settings["responseType"] == "text" ? xhr.responseText : xhr.responseXML; //返回值型別
                            if (((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) && typeof settings['onSucceed'] == 'function') { //成功
                                settings['onSucceed'](result, xhr.status); 
                            } else if (xhr.status >= 400 && xhr.status < 500) { //客戶端出錯,404啊神馬的
                                settings['onClientError'](result, xhr.status); 
                            } else if (xhr.status >= 500) { //伺服器端出錯
                                settings['onServerError'](result, xhr.status); 
                            } 
                        } 
                    } 
                    xhr.open(settings['method'], settings['url'], settings['user'], settings['password']); //傳送請求
                  
                    if (typeof settings['headers'] == 'object') { //設定自定義headers
                        var headers = settings['headers']; 
                        for (h in headers) { 
                            xhr.setRequestHeader(h, headers[h]); 
                        } 
                    } 
                    if(!settings['enableCache']){ //禁用快取
                        xhr.setRequestHeader("If-Modified-Since","0");
                        }
                    
                    if (settings["method"].toLowerCase() == "post") { //post請求
                        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); 
                        var data="";
                        if(typeof settings["data"]=='object')
                        {
                            for(d in settings["data"]){
                                data+=(d+'='+settings["data"][d]);
                                }
                          }else{
                            data=settings["data"];
                              }
                        xhr.send(data); //傳遞引數
                    } else { 
                        xhr.send(); //get請求
                    } 
                }

最後

這樣一個簡單的Ajax封裝就完成了,使用的時候和jQuery類似

ssLib.ajax({ 
            "url": "testajax.php",
            "data":{"name":"Byron"},
            "onSucceed": function(result) {
                alert(result);
            } 
        });

看起類不錯,不過沒實際使用過呢還,希望大家多給意見。

相關文章