您的位置:首页 > Web前端

前端通信:ajax设计方案(六)--- 全局配置、请求格式拓展和优化、请求二进制类型、浏览器错误搜集以及npm打包发布

2017-09-25 10:05 791 查看
距离上一次博客大概好多好多时间了,感觉再不搞点东西出来,感觉就废了的感觉。这段时间回老家学习驾照,修养,然后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上留言
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐