/**
* ajax和跨域jsonp
* Created by xgx on 2015-10-08.
*
* @param {string} url
* @param {Object} options
* {string} type 请求方式
* default: GET
* GET | POST
* {string | Object} data 数据
* 可以是对象或构造好的字符串
* {bool} crossDomain 是否跨域
* 跨域则使用jsonp异步方式
* {int} timeout 超时时间
* 单位ms
* default: 60 000
* {Function} error 失败回调
* {Function} success 成功回调
* {Function} resultFilter 结果过滤
* 根据结果来判断成功失败, 用来处理通用的已知错误, 仅支持jsonp
* {Function} complete 请求完成后回调
* 无论成功失败均会执行
* {string} jsonpCallback
* default: EA_cb + 自增值
* {string} jsonp 回调函数字段名
* default: callback,
* {bool} async 是否异步
* 默认为异步
* default: true, force true for crossDomain 'true'
* {bool} cache 缓存
* false仅在type 'GET' 时有效
* default: true
* {string} dataType 数据类型
* json时会自动解析, script时会自动执行
* default: xml,
* xml | json | script
*/
function ajax(url, options) {
//异步请求回调函数序号,从10000开始自增
this.jsonpIndex = this.jsonpIndex || 10000;
options = options || {};
options = {
type: options.type || "GET",
data: options.data || "",
complete: options.complete || new Function(),
error: options.error || new Function(),
success: options.success || new Function(),
resultFilter: options.resultFilter || new Function(),
//默认1min超时
timeout: options.timeout || 1000 * 60,
//jsonp
crossDomain: options.crossDomain || false,
jsonpCallback: options.jsonpCallback || "EA_cb" + this.jsonpIndex,
jsonp: options.jsonp || "callback",
//默认为异步
async: typeof(options.async) === "undefined" ? true : options.async,
cache: typeof(options.cache) === "undefined" ? true : options.cache,
dataType: options.dataType || ""
};
//处理data
var dataString = "";
if (typeof (options.data) === "object") {
for (var x in options.data) {
if (options.data.hasOwnProperty(x)) {
dataString += "&" + x + "=" + encodeURIComponent(options.data[x]);
}
}
options.data = dataString.substr(1);
}
//GET & JSONP 都通过URL传data
if (options.data && (options.type === "GET" || options.crossDomain)) {
url += (url.indexOf("?") !== -1) ? "&" : "?";
url += options.data;
}
//处理跨域请求
if (options.crossDomain) {
this.jsonpIndex++;
return jsonp(url, options);
}
//处理缓存
if (!options.cache && options.type === "GET") {
url += (url.indexOf("?") !== -1) ? "&" : "?";
url += "_=" + Math.random().toString().substr(2);
}
if (typeof XMLHttpRequest === "undefined") {
XMLHttpRequest = function () {
var xmlhttp;
if (window.ActiveXObject) {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
if (!xmlhttp) {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
} else {
alert("Init XMLHTTP Error!");
}
return xmlhttp;
}
}
var xml = new XMLHttpRequest();
xml.open(options.type, url, options.async);
var requestDone = false;
window.setTimeout(function () {
if (requestDone) {
return;
}
requestDone = true;
options.error();
}, options.timeout);
//监听文档状态的改变
xml.onreadystatechange = function () {
if (xml.readyState == 4 && !requestDone) {
requestDone = true;
if (httpSuccess(xml)) {
options.success(httpData(xml, options.dataType));
}
else {
options.error(xml, xml.status, xml.statusText);
}
options.complete();
//为避免内存泄漏,清理文档
xml = null;
}
};
//header
xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
try {
if (options.data) {
xml.send(options.data);
}
else {
xml.send(null);
}
}
catch (e) {
return null;
}
//JSONP跨域请求
function jsonp(url, options) {
var timeout_trigger = window.setTimeout(function () {
window[options.jsonpCallback] = new Function();
console.error("JSONP: Connect timeout: ", options.timeout);
options.error();
//清空,防止超时和出错时重复调用
options.error = new Function();
options.complete();
options.complete = new Function();
removeDom(options.jsonpCallback);
}, options.timeout);
var json;
url += (url.indexOf("?") !== -1) ? "&" : "?";
url += options.jsonp + "=" + options.jsonpCallback;
window[options.jsonpCallback] = function (data) {
window.clearTimeout(timeout_trigger);
options.complete();
if (options.dataType == "json") {
if (!data.length) {
console.error("JSONP: Json data is Empty , On URL : ", url);
options.error();
return;
}
try {
json = JSON.parse(data);
} catch (e) {
//json解析异常
console.error(
"JSONP: Json data parse error : ", e, ", data is : ", data, ", On URL : ", url
);
options.error();
return;
}
if (options.resultFilter(json)) {
options.error();
} else {
options.success(json);
}
} else {
options.success(data);
}
removeDom(options.jsonpCallback);
};
var script = document.createElement("script");
script.id = options.jsonpCallback;
script.type = "text/javascript";
script.async = true;
script.onerror = function () {
console.error("JSONP: Network Connect error!");
window.clearTimeout(timeout_trigger);
options.error();
options.error = new Function();
removeDom(options.jsonpCallback);
};
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
//删除指定Script标签
function removeDom(id) {
setTimeout(function () {
var dom = $ID(id);
if (dom) {
document.getElementsByTagName("head")[0].removeChild(dom);
}
//30s 后再清除, 避免出现加载问题
}, 30000);
}
//判断http响应是否成功
function httpSuccess(r) {
try {
return (!r.status && location.protocol == "file:") ||
(r.status >= 200 && r.status < 300) ||
r.status == 304 ||
(navigator.userAgent.indexOf("Safari") >= 0 &&
r.status === undefined);
}
catch (e) {
}
return false;
}
//从http响应中解析得到正确的数据
function httpData(r, type) {
var ct = r.getResponseHeader("Content-Type");
type = !type ? (ct.indexOf("xml") >= 0 ? "xml" : "") : type;
var data = type == "xml" ? r.responseXML : r.responseText;
if (type == "script") {
eval.call(window, data);
}
if (type == "json") {
try {
data = JSON.parse(data);
} catch (e) {
//json解析异常
console.error(
"JSONP: Json data parse error : ", e, ", data is : ", data, ", On URL : ", url
);
options.error();
return;
}
}
return data;
}
}
网友评论