import xhr from './xhr';
import isObject from './isObject';
import extend from './extend';
import each from './each';
import logger from './logger';
/** Ajax 请求成功回调
* @callback ajaxSuccessCallback
* @param {Object} data 请求成功后数据结果
*/
/** Ajax 请求失败回调
* @callback ajaxErrorCallback
* @param {Object} error 请求失败的异常结果
* @param {Number} status 错误代码,如 404
*/
/**
* @typedef {Object} AjaxRequestArg Ajax 请求参数
* @property {String} url 请求目标地址
* @property {Number} timeout 请求超时时间,若超时请求将终止
* @property {Boolean} credentials 标识是否携带 cookie
* @property {Boolean} cors 标识是否支持跨域
* @property {String} type 标识请求类型,如 'GET','POST'
* @property {ajaxSuccessCallback} success 请求成功回调
* @property {ajaxErrorCallback} error 请求失败的回调
* @property {object} header 请求头,Key/Value 键值对对象
* @property {Object} data 请求体,Key/Value 键值对对象
*/
/** 发起一个 Ajax 请求
* @category Bom
* @function ajax
* @param {AjaxRequestArg} para 请求参数
*
* @example
* ajax({
* url:'/example',
* timeout:15000,
* credentials:true,
* cors:true,
* type:'POST',
* success:function (data) { console.log(data)},
* error:function (data) { console.log(error)},
* header:{ExtraHeader:'TestValue'},
* data:{ name:'Alice', age:18 },
* })
*/
export default function ajax(para) {
para.timeout = para.timeout || 20000;
para.credentials = typeof para.credentials === 'undefined' ? true : para.credentials;
function getJSON(data) {
if (!data) {
return '';
}
try {
return JSON.parse(data);
} catch (e) {
return {};
}
}
var g = xhr(para.cors);
if (!g) {
return false;
}
if (!para.type) {
para.type = para.data ? 'POST' : 'GET';
}
para = extend(
{
success: function () { },
error: function () { }
},
para
);
var oldsuccess = para.success;
var olderror = para.error;
var errorTimer;
function abort() {
try {
if (g && typeof g === 'object' && g.abort) {
g.abort();
}
} catch (error) {
logger.log(error);
}
//如果 g.abort 未生效,手动执行 error
if (errorTimer) {
clearTimeout(errorTimer);
errorTimer = null;
para.error && para.error();
g.onreadystatechange = null;
g.onload = null;
g.onerror = null;
}
}
para.success = function (data,status) {
oldsuccess(data,status);
if (errorTimer) {
clearTimeout(errorTimer);
errorTimer = null;
}
};
para.error = function (err,status) {
olderror(err,status);
if (errorTimer) {
clearTimeout(errorTimer);
errorTimer = null;
}
};
errorTimer = setTimeout(function () {
abort();
}, para.timeout);
// eslint-disable-next-line no-undef
if (typeof XDomainRequest !== 'undefined' && g instanceof XDomainRequest) {
//XDomainRequest success callback
g.onload = function () {
para.success && para.success(getJSON(g.responseText), g.status);
g.onreadystatechange = null;
g.onload = null;
g.onerror = null;
};
//XDomainRequest error callback
g.onerror = function () {
para.error && para.error(getJSON(g.responseText), g.status);
g.onreadystatechange = null;
g.onerror = null;
g.onload = null;
};
}
g.onreadystatechange = function () {
try {
if (g.readyState == 4) {
if ((g.status >= 200 && g.status < 300) || g.status == 304) {
para.success(getJSON(g.responseText), g.status);
} else {
para.error(getJSON(g.responseText), g.status);
}
g.onreadystatechange = null;
g.onload = null;
}
} catch (e) {
g.onreadystatechange = null;
g.onload = null;
}
};
g.open(para.type, para.url, true);
try {
if (para.credentials) {
g.withCredentials = true;
}
if (isObject(para.header)) {
each(para.header, function (v, i) {
g.setRequestHeader && g.setRequestHeader(i, v);
});
}
if (para.data) {
if (!para.cors) {
//XDomainRequest no custom headers may be added to the request
g.setRequestHeader && g.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
}
if (para.contentType === 'application/json') {
g.setRequestHeader && g.setRequestHeader('Content-type', 'application/json; charset=UTF-8');
} else {
g.setRequestHeader && g.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
}
}
} catch (e) {
logger.log(e);
}
g.send(para.data || null);
}
Source