生命不息重構不止!
上一篇寫了一下我對ajax的再次封裝的方法,收到了很多有價值的回復,比如有童鞋建議用$.extend,一開始還以為要做成插件呢,后來才知道,原來這個東東還可以實現合並。省着自己再去做判斷了。
還有童鞋說“要不要多加點傳入參數”,這一下提醒我了,ajax有很多參數呀,常用的我考慮進來了,但是還有很多不常用的呢,如果需要的話怎么辦?在看看我調用原生ajax的方式,kao,完全不支持增加其他參數嗎,這怎么行,改一定要改。於是就改成了這樣。
1 //對ajax的封裝 //最基礎的一層封裝 2 Nature.Ajax = function(ajaxInfo) { 3 4 //定義默認值 5 //type: "GET", //訪問方式:如果dataPata不為空,自動設置為POST;如果為空設置為GET。 6 //dataType: Nature.AjaxConfig.ajaxDataType, //數據類型:JSON、JSONP、text 7 //cache: true, //是否緩存,默認緩存 8 //urlPara: {},//url后面的參數。一定會加在url后面,不會加到form里。 9 //formData: {},//表單里的參數。如果dataType是JSON,一定加在form里,不會加在url后面;如果dataType是JSONP的話,只能加在url后面。 10 //url: //依靠上層指定 11 12 //補全ajaxInfo 13 //dataType 14 if (typeof ajaxInfo.dataType == "undefined") ajaxInfo.dataType = Nature.AjaxConfig.ajaxDataType; 15 //cache 16 if (typeof ajaxInfo.cache == "undefined") ajaxInfo.cache = false; 17 18 //type 19 if (typeof ajaxInfo.formData == "undefined") { 20 ajaxInfo.type = "GET"; 21 } else { 22 ajaxInfo.type = "POST"; 23 ajaxInfo.data = ajaxInfo.formData; 24 } 25 26 //處理URL和參數 27 if (typeof ajaxInfo.urlPara != "undefined") { 28 var tmpUrlPara = ""; 29 var para = ajaxInfo.urlPara; 30 for (var key in para) { 31 tmpUrlPara += "&" + key + "=" + para[key]; 32 } 33 34 if (ajaxInfo.url.indexOf('?') >= 0) { 35 //原地址有參數,直接加 36 ajaxInfo.url += tmpUrlPara; 37 } else { 38 //原地址沒有參數,變成?再加 39 ajaxInfo.url += tmpUrlPara.replace('&', '?'); 40 } 41 } 42 43 //處理xhrFields 44 if (typeof ajaxInfo.xhrFields == "undefined") { 45 ajaxInfo.xhrFields = { 46 //允許cors跨域訪問時添加cookie 47 withCredentials: true 48 }; 49 } else { 50 if (typeof ajaxInfo.xhrFields.withCredentials == "undefined") { 51 ajaxInfo.xhrFields.withCredentials = true; 52 } 53 } 54 55 //處理error 56 var error = ajaxInfo.error; 57 ajaxInfo.error = function(request, textStatus, errorThrown) { 58 //訪問失敗,自動停止加載動畫,並且給出提示 59 alert("提交" + ajaxInfo.title + "的時候發生錯誤!"); 60 if (typeof top.spinStop != "undefined") 61 top.spinStop(); 62 if (typeof error == "function") error(); 63 }; 64 65 //處理success 66 var success = ajaxInfo.success; 67 ajaxInfo.success = function(data) { 68 //顯示調試信息 69 if (typeof(parent.DebugSet) != "undefined") 70 parent.DebugSet(data.debug); 71 72 if (typeof(ajaxInfo.ctrlId) == "undefined") 73 success(data); 74 else { 75 success(ajaxInfo.ctrlId, data); 76 } 77 }; 78 79 //開始執行ajax 80 $.ajax(ajaxInfo); 81 };
雖然還是只有一個參數,但是這個參數是一個集合。可以包含很多的元素(屬性)。改進后完全以這個參數為主,進行默認的屬性設置,最后直接把這個參數傳遞給原生ajax,這樣調用的時候,可以根據ajax的規則來設定自己需要的屬性了。
另外去掉了 defaultInfo。因為看來看去,就是一個Nature.sendDataType 算是默認值,其他的都不算了。所以干脆去掉吧。改進后既可以很方便的調用,也確保了其擴展性,可以增加其他的屬性。
1 var ajax = Nature.Ajax; 2 3 ajax({ 4 url:"", 5 formData: jsonValue, 6 urlPara: ajaxUrlPara, 7 title: "保存數據", 8 success: function(data) { 9 if (data.err.length == 0) { 10 alert("保存成功!"); 11 //清空表單 12 13 } else { 14 alert(data.err); 15 } 16 17 if (typeof callback == "function") { 18 callback(); 19 } 20 21 } 22 });
好像還是要寫不少東東,但是仔細看看的話,可以發現有很多優勢,首先明確了哪些參數用url傳遞,哪些參數用表單post傳遞。error有了統一的處理,蘇測試時success了也可以統一顯示調試信息。不用去考慮是post還是get是json還是jsonp,這些都會統一處理。
最后涉及到了一個並發的問題,因為我想實現“復用”,這個函數會被加載到top頁面里,其他的子頁面都會到top里調用這個函數,那么如果同時打開兩個iframe,一起加載,並發了怎么辦?會不會產生沖突?如果new的話,並發的時候肯定不會產生沖突,但是jQuery的ajax似乎沒有new,那么他是如何處理並發的呢?
我是實踐派,遇到問題了首先想到的是寫點代碼測試一下,然后再去找找原理和理論。於是我就寫了個代碼模擬測試一下,看看並發的情況。
1 var state = 1; 2 3 function fun1(para, timestep) { 4 var temp = para.a1;//內部變量 5 6 para.a1 = para.a1 * 100;//修改參數看看 7 8 this.time = timestep;//這個不new的時候能用嗎? 9 10 var self = this;//setTimeout里面用不了這個this,那么江湖規矩。 11 12 state ++;//全局變量,不解釋 13 14 window.setTimeout(function() { //模擬回調 15 console.log(para.name); 16 console.log("para.a1 : " + para.a1); 17 console.log("temp:" + temp); 18 console.log("this.time: " + self.time); 19 20 21 },timestep); 22 } 23 24 fun1({ name: "aa1",a1:10 }, 1000); 25 fun1({ name: "aa2", a1: 20 }, 100); 26 27 var f1 = new fun1({ name: "aa3", a1: 30 }, 10);
大家猜猜輸出結果是啥?