前端通訊:ajax設計方案(六)--- 全局配置、請求格式拓展和優化、請求二進制類型、瀏覽器錯誤蒐集以及npm打包發佈

距離上一次博客大概好多好多時間了,感受再不搞點東西出來,感受就廢了的感受。這段時間回老家學習駕照,修養,而後7月底來上海求職(面了4家,拿了3家office),而後入職同程旅遊,項目趕進度等等一系列的緣由,致使沒有太多時間去搞東西。感受虧欠了好多,因此此次一次性補上。廢話很少說了,咱們直接進入主題。前端

介紹此次講解的庫的更新vue

  •   ajax全局配置
  •   請求參數的拓展(增長json)和重構優化
  •   初始化參數類型檢查
  •   瀏覽器錯誤回收機制
  •   增長ajax請求blob(二進制)類型
  •   跨域問題的總結和支持
  •   npm打包發佈

 

ajax全局配置git

  對於這個東西,相信你們都頗有感觸,在咱們開發中的場景也不少,例如github

  1.   接口名稱前統一有"api/core"這個,可是在咱們每次請求不想寫這麼多,就能夠配置到baseURL中
  2.   請求接口後端定義一些公告參數,每次都要傳輸
  3.  爲了一些業務,每次在http-header中設置 一些參數值
  4.   統一設置接口超時時間
  5.   統一錯誤、超時處理函數
  6.   發送請求前、得到請求參數後對參數處理
  7.   ....

  因此有了這個玩意,我只是定義一些經常使用的基礎的,其餘的你們能夠根據本身業務需求進行拓展和改造,而後push一個分支,我會討論協商以後採納的。代碼以下:web

  PS:這公共參數玩意我忘了去限制了,若是傳輸和其餘初始化參數同樣的會覆蓋的,下個版本進行改進,見諒。ajax

        //經過拋出的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)和重構優化npm

  在以前寫的庫中,只針對請求作了通用的請求和form請求,可是針對經常使用的請求類型json格式沒有支持,因此此次將這個參數進行支持(主要咱們項目中用到了,可是我寫的庫沒有,因此支持)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)
            }

  

初始化參數類型檢查api

  初始化參數檢查這個功能主要在每一個請求中,可能不是定義的參數都想傳輸的,好比我作瀏覽器錯誤回收的時候,我只想將這個錯誤的信息發送到錯誤回收地址,我不須要作任何處理,只須要發出去,無論成不成功。因此我只有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考慮到瀏覽器的兼容性錯誤地方不一樣,並且要將錯誤回收地址的錯誤忽略掉,並且要考慮何時切入監控這個點最好等等,並且要配置進主流程能動態配置,哎不說了,下期吧。順便下期將前端接口容錯機制加上去,好比監控到40四、50三、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上留言

相關文章
相關標籤/搜索