npm i ajax-js / yarn add ajax-js
//每次清空请求缓存,并重新合并对象
var ajaxSetting = tool.checkParam(options), sendData = '';
//创建xhr对象
var xhr = tool.createXhrObject();
//针对某些特定版本的mozillar浏览器的BUG进行修正
xhr.overrideMimeType ? (xhr.overrideMimeType("text/javascript")) : (null);
//针对IE8的xhr做处理 PS:ie8下的xhr无xhr.onload事件,所以这里做判断
xhr.onload === undefined ? (xhr.xhr_ie8 = true) : (xhr.xhr_ie8 = false);
//参数处理(get和post),包括xhr.open get:拼接好url再open post:先open,再设置其他参数
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':
sendData = JSON.stringify(tool.MergeObject(ajaxSetting.data, ajaxSetting.publicData))
ajaxSetting.requestHeader['Content-Type'] = 'application/json'
break
case '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)
}
xhr.responseType = ajaxSetting.responseType;
//设置超时时间(只有异步请求才有超时时间)
ajaxSetting.async ? (xhr.timeoutEvent = ajaxSetting.timeout) : (null);
//设置http协议的头部
tool.each(ajaxSetting.requestHeader, function (item, index) {
xhr.setRequestHeader(index, item)
});
//onload事件(IE8下没有该事件)
xhr.onload = function (e) {
if (this.status == 200 || this.status == 304) {
/*
* ie浏览器全系列不支持responseType='json',所以在ie下使用JSON.parse进行转换
* */
if (ajaxSetting.responseType === 'json') {
if (isNaN(tool.getIEVersion())) {
ajaxSetting.successEvent(ajaxSetting.transformResponse(xhr.response));
} else {
ajaxSetting.successEvent(ajaxSetting.transformResponse(JSON.parse(xhr.responseText)));
}
} else {
ajaxSetting.successEvent(ajaxSetting.transformResponse(xhr.response));
}
} else {
/*
* 这边为了兼容IE8、9的问题,以及请求完成而造成的其他错误,比如404等
* 如果跨域请求在IE8、9下跨域失败不走onerror方法
* 其他支持了Level 2 的版本 直接走onerror
* */
ajaxSetting.errorEvent(e.currentTarget.status, e.currentTarget.statusText);
}
};
//xmlhttprequest每次变化一个状态所监控的事件(可拓展)
xhr.onreadystatechange = function () {
switch (xhr.readyState) {
case 1://打开
//do something
break;
case 2://获取header
//do something
break;
case 3://请求
//do something
break;
case 4://完成
//在ie8下面,无xhr的onload事件,只能放在此处处理回调结果
if (xhr.xhr_ie8) {
if (xhr.status == 200 || xhr.status == 304) {
if (ajaxSetting.responseType == "json") {
ajaxSetting.successEvent(ajaxSetting.transformResponse(JSON.parse(xhr.responseText)))
}
}
}
break;
}
;
};
//ontimeout超时事件
xhr.ontimeout = function (e) {
ajaxSetting.timeoutEvent("000000", e ? (e.type) : ("timeoutEvent")); //IE8 没有e参数
xhr.abort(); //关闭请求
};
//错误事件,直接ajax失败,而不走onload事件
xhr.onerror = function (e) {
ajaxSetting.errorEvent(e)
//错误日志上传
// tool.uploadAjaxError({
// errInfo: e.currentTarget.statusText,
// errUrl: tool.checkRealUrl(ajaxSetting),
// errLine: e.currentTarget.status,
// Browser: navigator.userAgent
// })
};
//发送请求
xhr.send(ajaxSetting.type === 'get' ? '' : sendData);
ajax.post("/api/ajax1/ajaxT1/",{"name":"测试异步post请求","age":"success"},function(data){alert(data)}); //该接口在1122上
ajax.post("http://192.168.0.3:2211/api/weixin/ajaxT2/",{"name":"测试跨域post请求","age":"success"},function(data){alert(data)});
/// <summary>
/// 测试跨域请求
/// </summary>
/// <param name="module"></param>
/// <returns></returns>
[Route("ajaxT2")]
public String kuaAjaxT2([FromBody]TModule module)
{
String result = "跨域post传输成功:"+module.name+"-"+module.age;
return result;
}
/// <summary>
/// 测试ajax同源请求
/// </summary>
/// <param qwer="code"></param>
/// <returns>result</returns>
[Route("ajaxT2")]
public String GetkuaAjaxT1(string name,string age)
{
String result = "1J跨域成功:" + name + "-" + age;
return result;
}
/*
* 长轮询的实现
* param: type 请求类型
* url 请求接口地址
* data 请求参数
* successEvent(data,this) 成功事件处理 如果得到正确数据,则让轮询停止,则在第二个回调参数设置stop属性就好
* timeFrequency 每隔多少时间发送一次请求
* errorEvent 错误事件
* timeoutEvent 超时处理
* */
longPolling: function (type, url, data, successEvent, timeFrequency, errorEvent, timeoutEvent) {
var ajaxParam = {
type: type,
url: url,
data: data,
successEvent: function (dateCall) {
successEvent(dateCall, this);
if (!this.stop) {
setTimeout(function () {
tempObj.longPolling(type, url, data, successEvent, timeFrequency, errorEvent, timeoutEvent);
}, timeFrequency);
}
;
},
//如果走了error说明该接口有问题,没必要继续下去了
errorEvent: errorEvent,
timeoutEvent: function () {
timeoutEvent();
setTimeout(function () {
tempObj.longPolling(type, url, data, successEvent, timeFrequency, errorEvent, timeoutEvent)
}, timeFrequency);
}
};
ajax.common(ajaxParam);
},
考虑到业务需求
聊天系统会要一直需求轮询,不间断的向后台使用数据,所以isAll = true
等待付款业务只需要得到后台一次响应是否支付成功,所以使用回调参数中的第二个参数的stop属性,结束轮询
/*
* ajax上传文件 -- level2的新特性,请保证你的项目支持新的特性再使用
* url 文件上传地址
* fileSelector input=file 选择器
* size 文件限制大小
* fileType 文件限制类型 mime类型
* successEvent 上传成功处理
* errorEvent 上传失败处理
* timeoutEvent 超时处理
*
* return: status: 0 请选择文件
* 1 超出文件限制大小
* 2 非允许文件格式
* */
upload: function (url, fileSelector, size, fileType, successEvent, errorEvent, timeoutEvent) {
var formdata = new FormData(), fileNode = document.querySelector(fileSelector),
fileCount = fileNode.files.length, data = {}, result = {};
//以下为上传文件限制检查
if (fileCount > 0) {
tool.each(Array.prototype.slice.call(fileNode.files), function (value) {
//检查文件大小
if (value.size > size) {
result["status"] = 1;
result["errMsg"] = "超出文件限制大小";
} else {
if (fileType != "*") {
//检查文件格式.因为支持formdata,自然支持数组的indexof(h5)
if (fileType.indexOf(value.type) === -1) {
result["status"] = 2;
result["errMsg"] = "非允许文件格式";
} else {
formdata.append(value.name, value);
}
;
} else {
formdata.append(value.name, value);
}
}
;
});
} else {
result["status"] = 0;
result["errMsg"] = "请选择文件";
}
;
if (result.status !== undefined) return result; //如果有错误信息直接抛出去,结束运行
var ajaxParam = {
type: "post",
url: url,
data: formdata,
contentType: 'form',
successEvent: successEvent,
errorEvent: errorEvent,
timeoutEvent: timeoutEvent
};
ajax.common(ajaxParam);
},
如果想要看文件上传具体内容和测试各种结果,请转到这片博客:http://www.cnblogs.com/GerryOfZhong/p/6274536.html
/*
* ajax大文件切割上传(支持单个文件) -- level2的新特性,请保证你的项目支持新的特性再使用
* url 文件上传地址
* fileSelector input=file 选择器
* cutSize 切割文件大小
* fileType 文件限制类型 mime类型
* successEvent 上传成功处理
* progressEvent 上传进度事件
* errorEvent 上传失败处理
* timeoutEvent 超时处理事件
*
* return: status: 0 请选择文件
* 1 非允许文件格式
* */
upload_big: function (url, fileSelector, cutSize, fileType, successEvent, progressEvent, errorEvent, timeoutEvent) {
var file = document.querySelector(fileSelector).files, result = {};
//以下为上传文件限制检查
if (file.length === 1) {
if (fileType != "*") {
if (fileType.indexOf(file.type) === -1) {
result["status"] = 1;
result["errMsg"] = "非允许文件格式";
}
}
} else {
result["status"] = 0;
result["errMsg"] = "请选择文件/只能上传一个文件";
}
;
if (result.status !== undefined) return result; //如果有错误信息直接抛出去,结束运行
//判断上传文件是否超过需要切割的大小
if (file[0].size > cutSize) {
var fileArr = tool.cutFile(file[0], cutSize); //切割文件
cutFile_upload(fileArr);
} else {
var fileForm = new FormData();
fileForm.append("name", file[0].name);
fileForm.append("file".name, file[0]);
fileForm.append("count", 1);
fileForm.append("cutSize", cutSize);
var ajaxParam = {
type: "post",
url: url,
data: fileForm,
contentType: 'form',
successEvent: function (data) {
successEvent(data);
progressEvent(1, 1);
},
errorEvent: errorEvent,
timeoutEvent: timeoutEvent
};
ajax.common(ajaxParam);
}
;
/*
* 切割文件上传,配合后台接口进行对接
* 传输参数:
* count -- 当前传输part的次数
* name -- 做过处理的文件名称
* file -- 上传的.part的切割文件
* isLast -- 是否为最后一次切割文件上传(默认值:"true" 字符串,只有最后一次才附加)
* */
function cutFile_upload(fileArr, count) {
var formData = new FormData();
if (count == undefined) {
count = 0;
formData.append("name", fileArr[0].name);
formData.append("file".name, fileArr[0].file);
} else {
if (count === fileArr.length - 1) {
formData.append("isLast", "true")
}
;
formData.append("name", fileArr[count].name);
formData.append("file".name, fileArr[count].file);
}
formData.append("count", count);
formData.append("cutSize", cutSize);
;
var ajaxParam = {
type: "post",
url: url,
data: formData,
contentType: 'form',
successEvent: function (data) {
/*
* data 参数设置 需要后台接口配合
* 建议:如果后台成功保存.part文件,建议返回下次所需要的部分,比如当前发送count为0,则data返回下次为1。
* 如果保存不成功,则可false,或者返回错误信息,可在successEvent中处理
*
* */
progressEvent(count + 1, fileArr.length); //上传进度事件,第一个参数:当前上传次数;第二个参数:总共文件数
var currCount = Number(data);
if (currCount) {
if (currCount != fileArr.length) {
cutFile_upload(fileArr, currCount);
}
;
}
;
successEvent(data); //成功处理事件
},
errorEvent: errorEvent,
timeoutEvent: timeoutEvent
};
ajax.common(ajaxParam);
}
}
如果想要看文件上传具体内容和测试各种结果,请转到这片博客:http://www.cnblogs.com/GerryOfZhong/p/6295211.html
备注:ajax的上传技术,在es5+之后支持,浏览器的兼容性就是除了IE10以下,大部分都支持了
如果想要看文件上传具体内容和测试各种结果,请转到这片博客:http://www.cnblogs.com/GerryOfZhong/p/7096792.html
由于内容比较多,比较难粘贴代码,如果想要看具体内容和测试各种结果,请转到博客
博客园:http://www.cnblogs.com/GerryOfZhong/p/7575820.html
知乎:https://zhuanlan.zhihu.com/p/29640921
此次对于请求的错误监控进行了搜集,前端的负载均衡,将流量打到不同的服务器上,以及在请求宕机之后的备份切换
每次迭代都会对新的代码做测试讲解,所以篇幅比较多,so
博客园:https://www.cnblogs.com/GerryOfZhong/p/9245510.html
知乎:https://zhuanlan.zhihu.com/p/38685979
本次包括了设计阶段,摸索阶段,实现阶段,最后全面覆盖测试阶段(包括数据搜集清洗),还有与主流前端通信框架进行对比PK阶段。
博客园:https://www.cnblogs.com/GerryOfZhong/p/9630569.html
知乎:https://zhuanlan.zhihu.com/p/44477183
本地仅增加了文档的支持,请移步ajax-api/api.md 查看
本次包括完善了整个Promise A+ 规范,实现了ES6全部功能,以及增加了ajax库支持mock数据的能力。
博客园:https://www.cnblogs.com/GerryOfZhong/p/10726306.html
知乎:https://zhuanlan.zhihu.com/p/44477183