框架基礎:ajax設計方案(六)--- 全局配置、請求格式拓展和優化、請求二進制類型、瀏覽器錯誤搜集以及npm打包發布
距離上一次博客大概好多好多時間了,感覺再不搞點東西出來,感覺就廢了的感覺。這段時間回老家學習駕照,修養,然後7月底來上海求職(面了4家,拿了3家office),然後入職同程旅遊,項目趕進度等等一系列的原因,導致沒有太多時間去搞東西。感覺虧欠了好多,所以這次一次性補上。廢話不多說了,我們直接進入主題。
介紹這次講解的庫的更新:
- ajax全局配置
- 請求參數的拓展(增加json)和重構優化
- 初始化參數類型檢查
- 瀏覽器錯誤回收機制
- 增加ajax請求blob(二進制)類型
- 跨域問題的總結和支持
- npm打包發布
ajax全局配置
對於這個東西,相信大家都很有感觸,在我們開發中的場景也很多,例如
- 接口名稱前統一有"api/core"這個,但是在我們每次請求不想寫這麽多,就可以配置到baseURL中
- 請求接口後端定義一些公告參數,每次都要傳輸
- 為了一些業務,每次在http-header中設置 一些參數值
- 統一設置接口超時時間
- 統一錯誤、超時處理函數
- 發送請求前、獲得請求參數後對參數處理
- ....
所以有了這個玩意,我只是定義一些常用的基礎的,其他的大家可以根據自己業務需求進行拓展和改造,然後push一個分支,我會討論協商之後采納的。代碼如下:
PS:這公共參數玩意我忘了去限制了,如果傳輸和其他初始化參數一樣的會覆蓋的,下個版本進行改進,見諒。
//通過拋出的config方法設置全局參數 ajax.config({ baseURL: ‘‘, //通用url前綴 requestHeader: {}, //公共頭部 publicData: {}, //公共參數 timeout: 5000, //超時時間 responseType: ‘json‘, //response參數類型,默認‘json‘contentType: ‘‘, //請求參數類型(‘‘、‘json‘、‘form‘) withCredentials: true, //是否啟用跨域憑證傳輸 isOpenErr: true, //是否開啟瀏覽器錯誤回收 errURL: ‘‘, //瀏覽器錯誤回收地址 //請求發送前對數據進行處理 transformRequest: function (data) { return data; }, //得到正確請求後做的處理 transformResponse: function (data) { return data; }, //請求錯誤處理 errorEvent: function (x, xx, xxx) { }, //請求超時處理 timeoutEvent: function (code, e) { } })
請求參數的拓展(增加json)和重構優化
在之前寫的庫中,只針對請求做了通用的請求和form請求,但是針對常用的請求類型json格式沒有支持,所以這次將這個參數進行支持(主要我們項目中用到了,但是我寫的庫沒有,所以支持)
其次所謂的重構優化,只是感覺之前的代碼太TM挫了。不利於拓展和維護,所以這次將它進行優化。
//參數處理 if (ajaxSetting.data) { //有數據做參數處理 switch (ajaxSetting.contentType) { case ‘‘: //通用請求 tool.each(tool.MergeObject(ajaxSetting.data, ajaxSetting.publicData), function (item, index) { sendData += (index + "=" + item + "&") }); sendData = sendData.slice(0, -1); ajaxSetting.requestHeader[‘Content-Type‘] = ‘application/x-www-form-urlencoded‘ break case ‘json‘: //json請求 sendData = JSON.stringify(tool.MergeObject(ajaxSetting.data, ajaxSetting.publicData)) ajaxSetting.requestHeader[‘Content-Type‘] = ‘application/json‘ break case ‘form‘: //form請求 if (!tool.isEmptyObject(ajaxSetting.publicData)) { tool.each(ajaxSetting.publicData, function (item, index) { ajaxSetting.data.append(index, item) }) } sendData = ajaxSetting.data break } //請求前處理參數 sendData = ajaxSetting.transformRequest(sendData) //判斷請求類型 if (ajaxSetting.type === ‘get‘) { xhr.open(ajaxSetting.type, tool.checkRealUrl(ajaxSetting) + ‘?‘ + sendData, ajaxSetting.async) } else { xhr.open(ajaxSetting.type, tool.checkRealUrl(ajaxSetting), ajaxSetting.async) } } else { xhr.open(ajaxSetting.type, ajaxSetting.baseURL + ajaxSetting.url, ajaxSetting.async) }
初始化參數類型檢查
初始化參數檢查這個功能主要在每個請求中,可能不是定義的參數都想傳輸的,比如我做瀏覽器錯誤回收的時候,我只想將這個錯誤的信息發送到錯誤回收地址,我不需要做任何處理,只需要發出去,不管成不成功。所以我只有post2個參數,地址和錯誤信息。如果不做參數檢查,合並參數的時候,會把undefind合並到初始化參數中,導致程序宕機,容錯性、健壯性特別差,這樣的程序當雖然是我們都不想看到和去寫的,所以做了這塊。代碼如下:
類型檢查代碼:
//類型判斷 is: (function checkType() { var is = { types: ["Array", "Boolean", "Date", "Number", "Object", "RegExp", "String", "Window", "HTMLDocument", "function", "FormData"] }; for (var i = 0, c; c = is.types[i++];) { is[c] = (function (type) { return function (obj) { var temp; if (type === "function") { temp = typeof obj == type } else { temp = Object.prototype.toString.call(obj) == "[object " + type + "]"; } return temp; } })(c); } ; return is; })(),
批量處理代碼:
//批量檢查數據類型 checkDataTypeBatch: function (obj, objType) { var temp = true; tool.each(obj, function (value, key) { var typeName = objType[key], tempOutput; if (tool.is.Array(typeName)) { tool.each(typeName, function (item) { tempOutput = tempOutput || tool.is[item](value); }) } else { tempOutput = tool.is[typeName](value) } //如果格式不對,將錯誤數據恢復到初始化數據 if (!tempOutput) { obj[key] = initParam[key] } }) return temp; },
初始化數據和初始化數據類型
//默認參數 var initParam = { url: "", type: "", baseURL: ‘‘, data: {}, async: true, requestHeader: {}, publicData: {}, timeout: 5000, responseType: ‘json‘, contentType: ‘‘, withCredentials: false, isOpenErr: false, errURL: ‘‘, transformRequest: function (data) { return data; }, transformResponse: function (data) { return data; }, successEvent: function (data) { }, errorEvent: function (x, xx, xxx) { }, timeoutEvent: function (code, e) { } }; //初始化參數固定類型檢查 var initParamType = { url: "String", type: "String", baseURL: ‘String‘, data: [‘Object‘, ‘FormData‘], async: ‘Boolean‘, requestHeader: ‘Object‘, publicData: ‘Object‘, timeout: ‘Number‘, responseType: ‘String‘, contentType: ‘String‘, withCredentials: ‘Boolean‘, isOpenErr: ‘Boolean‘, errURL: ‘String‘, transformRequest: ‘function‘, transformResponse: ‘function‘, successEvent: ‘function‘, errorEvent: ‘function‘, timeoutEvent: ‘function‘ };
PS:可能不會將所有的所有的都考慮進去,但是這些已經能完成我暫時的需求了,如果想對這個方法做補充的,可以直接郵件或者github提交分支,然後驗證討論完善會合並到master上的
瀏覽器錯誤回收機制
瀏覽器錯誤回收這個概念,一般的公司是不會做的,只有那種針對廣泛用戶,廣泛瀏覽器兼容性的產品才會做。因為可能在主流瀏覽器上會出現問題,畢竟將市面上所有瀏覽器都做測試,對於公司的測試人員來說都是一個極大的工作量,所以相對來說肯定有很多忽略的,但是對於公司來說,每個客戶都是一種珍貴的資源,在不破壞主流的基礎上還是需要兼容的。所以回收這些錯誤,才顯得重要。
其次,還有更重要的一點,對於線上的bug和隱形的bug,永遠是重大的生產問題,在大公司會被問責的。所以瀏覽器錯誤搜集才顯得更加重要,在沒有被擴大之前能及時回收到才是最重要的。因為我曾在極客頭條這個網站遇到過,他們更新版本後登錄接口請求參數變化了,但是對於前端來說並沒有響應處理,導致登錄不上。這樣的問題,如果發生在淘寶上的話,一個部門會直接被問責的。
so,有這個想法就做了,而且我這主要寫了前端通信,所以順便加進去了。(PS:現在只做了瀏覽器的錯誤搜集處理,對於ajax的錯誤處理沒有監控,下個版本補上。畢竟接口的404等錯誤,瀏覽器onerror是不會觸發的)
//監控瀏覽器的錯誤日誌 setOnerror: function () { window.onerror = function (errInfo, errUrl, errLine) { tempObj.post(initParam.errURL, { errInfo: errInfo, //錯誤信息 errUrl: errUrl, //錯誤地址 errLine: errLine, //錯誤行號 Browser: navigator.userAgent //瀏覽器版本 }) } },
so,看完了是不是很簡單,其實就是這麽簡單,ajax接口錯誤監控暫時沒有最好的方案,因為在ajax考慮到瀏覽器的兼容性錯誤地方不同,而且要將錯誤回收地址的錯誤忽略掉,而且要考慮什麽時候切入監控這個點最好等等,而且要配置進主流程能動態配置,哎不說了,下期吧。順便下期將前端接口容錯機制加上去,比如監控到404、503、403等錯誤信息,前端接口自動將請求地址切換到備用地址,保證程序的健壯性。
增加ajax請求blob(二進制)類型
這個功能是之前想做的,不知道有沒有真實場景進行使用的。我做的測試只是針對一個圖片做的測試,請求一個二進制圖片,然後反顯。但是後期的場景可能比較重要,瀏覽器通過ajax流式下載文件等等,這個功能待定吧。
//獲取blob數據集代碼 obtainBlob: function (type, url, data, successEvent, errorEvent, timeoutEvent) { var ajaxParam = { type: type, url: url, data: data, responseType: ‘blob‘, successEvent: successEvent, errorEvent: errorEvent, timeoutEvent: timeoutEvent }; ajax.common(ajaxParam); },
//test ObtainBlob(確保地址正確)測試代碼 ajax.obtainBlob("get","http://10.73.1.198:9999/Scripts/lei.jpg", ‘‘, function (getData) { var reader = new FileReader(); reader.readAsDataURL(getData) reader.onload = function (e) { document.querySelector("#imgICO").setAttribute(‘src‘,e.target.result) } console.log(typeof getData); });
關於跨域的問題支持
跨域隔離:瀏覽器的core中,針對跨域為了安全做了限制,在跨域的時候將不會把cookie等憑證的數據進行服務器和客戶端之間回傳。所以,為了更快的請求靜態資源,可以將本項目中的靜態資源放到不同的域中,這樣進行跨域了,所以傳輸的請求比較小,速度也更快
但是,在多項目中,肯定會和其他項目組合作,so,有時候會需要這些憑證做一些自動登錄、身份驗證等功能。所以會需要進行憑證傳輸。
在XMLHttprequest中有個屬性withCredentials,這個屬性控制前端是否傳輸憑證信息(全局配置中已加),當然服務器也需要設置跨域請求的頭部:"Access-Control-Allow-Credentials: true"。這樣就可以愉快的玩耍啦
npm打包發布
這是最後一個了,也是完成一個關註的人的建議。在之前的博客中,有個朋友進行建議的,所以我進行了搜索、改造、發布、測試。所以時間周期有點長了。
npm:ajax-js
安裝:npm i ajax-js / yarn add ajax-js
使用:在頁面中引入,然後使用
<template> <div id="app"> select file:<input type="file" id="file1" accept="*"/><br/> <input type="button" id="upload" value="upload"/> <input type="button" id="uploadBig" value="uploadBig"/> <img id="imgICO"/> </div> </template> <script> import _ajax from ‘ajax-js‘ export default { name: ‘app‘, created(){ _ajax.get(‘http://10.73.1.198:9999/api/cores/getAjax/‘,{name:‘get請求成功‘,age:11},function (res) { console.log(res.name) }) //test post _ajax.post("http://10.73.1.198:9999/api/cores/postAjax/",{name:‘post請求測試成功‘,age:1},function(getData){ console.log(getData.name); }); // var formData = new FormData(); formData.append("name", "post Form請求測試成功"); formData.append("age", 11); _ajax.postFormData("http://10.73.1.198:9999/api/cores/postForm/",formData,function (res) { console.log(res.name) }) // //test post // _ajax.postJSON("http://10.73.1.198:9999/api/cores/postAjax/",{name:‘postJSON請求測試成功‘,age:1},function(getData){ // console.log(getData.name); // }); //test ObtainBlob(確保地址正確) // ajax.obtainBlob("get","http://10.73.1.198:9999/Scripts/lei.jpg", ‘‘, function (getData) { // var reader = new FileReader(); // reader.readAsDataURL(getData) // reader.onload = function (e) { // document.querySelector("#imgICO").setAttribute(‘src‘,e.target.result) // } // console.log(typeof getData); // }); //promise一般測試 _ajax.promiseAjax(‘http://10.73.1.198:9999/api/cores/postReqSleep/‘,{name:‘promise高延遲接口測試1‘,age:123}) .then(function (res) { console.log(res.name) return _ajax.promiseAjax(‘http://10.73.1.198:9999/api/cores/postAjax/‘,{name:‘promise一般接口測試2‘,age:456}) }).then(function (res) { console.log(res.name) }) // //並發promise測試 _ajax.promiseAjax(‘http://10.73.1.198:9999/api/cores/postAjax/‘,{name:‘promise並發接口測試3‘,age:123456}) .then(function (res) { console.log(res.name) return _ajax.promiseAjax(‘http://10.73.1.198:9999/api/cores/postReqSleep/‘,{name:‘promise並發高延遲接口測試4‘,age:456789}) }).then(function (res) { console.log(res.name) }) // var longTemp = 0; _ajax.longPolling(‘post‘,‘http://10.73.1.198:9999/api/cores/postAjax/‘,{name:‘輪詢測試‘,age:123456},function (res,that) { console.log(res.name+longTemp) longTemp+=1; if (longTemp === 10){ that.stop = true; } },1000) // }, mounted(){ //test post _ajax.postJSON("api/postAjax",{name:‘postJSON請求測試成功‘,age:1},function(getData){ console.log(getData.name); }); //test uploadFile document.querySelector("#upload").onclick = function () { var temp = _ajax.upload("http://10.73.1.198:9999/api/cores/upload/","#file1",1024*1024,[‘image/png‘],function(x){ }) console.log(temp); }; // // //test uploadFile document.querySelector("#uploadBig").onclick = function () { JSON.parse(‘‘) // var temp = ajax.upload_big("api/cores/uploadBig/","#file1",1024*1024,"*",function(x){},function(count,all){console.log("當前傳輸進度:"+count+"/"+all);}) var temp = _ajax.upload_big("http://10.73.1.198:9999/api/cores/uploadBig/","#file1",1024*1024,"*",function(x){},function(count,all){console.log("當前傳輸進度:"+count+"/"+all);}) console.log(temp); }; } } </script> <style> #app { font-family: ‘Avenir‘, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
PS:這個是在vue中的進行測試的。測試結果如下。
以下為不用npm安裝的測試,測試頁面在github上,後端接口用的.net,也在上面,看圖:
看一般頁面的測試結果
錯誤搜集接口查看
好啦,這個版本已經發布好了,有新的需求就籌劃下個版本的東西啦。最近在研究SSE,也就是前端的服務器推送玩意,準備這段時間總結出一套東西,順便針對這個技術本身的一些技術局限設計解決一些方案,比如SSE只能默認推送所有人,可以設計針對單個人去推送等等
代碼已集成github和npm打包:https://github.com/GerryIsWarrior/ajax / npm i ajax-js 點顆星星是我最大的鼓勵,有什麽問題可以博客、郵箱、github上留言
框架基礎:ajax設計方案(六)--- 全局配置、請求格式拓展和優化、請求二進制類型、瀏覽器錯誤搜集以及npm打包發布