Skip to content

Instantly share code, notes, and snippets.

@yangfch3
Last active Mar 23, 2020
Embed
What would you like to do?
ajax 请求封装
var Ajax = (function() {
var methodsList = ['get', 'post', 'head', 'options', 'put', 'connect', 'trace', 'delete'];
/**
* Ajax
* @param {String} url
* @param {Function} callback
* @param {Object/String} data
* @param {Object} options
*
*/
function Ajax(url, callback, data, options) {
// 顺序:new XHR --> onreadystatechange ---> open() ---> other callback or property ---> send()
var xhr = (function() {
// 使用 typeof 不会报错
if (typeof XMLHttpRequest !== undefined) {
return new XMLHttpRequest();
} else if (typeof ActiveXObject !== undefined) {
if (typeof arguments.callee.activeXString !== 'string') {
var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'],
i, len;
for (i = 0, len = versions.length; i < len; i++) {
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (error) {
console.log('Your Browser do not support ' + versions[i] + '.');
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error('没有可用的 AJAX 对象构造器');
}
})();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
try {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
if (callback) {
callback(xhr.responseText, xhr.status, xhr);
} else {
console.log(xhr);
}
} else {
console.error('请求错误: ' + xhr.status + ' ' + xhr.statusText);
}
} catch (error) {
console.error('回调函数内部发生错误,请检查回调函数!');
}
}
};
var method = (options && options.method && methodsList.indexOf(options.method.toLowerCase()) + 1) ? options.method : 'get';
if (method.toLowerCase() === 'get') {
if (typeof data === 'object' && data !== null) {
url = (function() {
var queryArr = [];
for (var prop in data) {
if (data.hasOwnProperty(prop)) {
queryArr.push(encodeURIComponent(prop) + '=' + encodeURIComponent(data[prop]));
}
}
return (url + '?' + queryArr.join('&'));
})();
data = null;
} else if (typeof data === 'string') {
data = data.indexOf('?') === 0 ? data : '?' + data;
url = url + data;
data = null;
} else {
data = null;
}
} else {
// 对于 POST,data 可以是null、字符串、文件(表单文件控件取得)、FormData、ArrayBuffer
if (data instanceof FormData || data instanceof File || data instanceof ArrayBuffer) {
data = data;
} else if (typeof data === 'object') {
data = function() {
var serializeArr = [];
for (var prop in data) {
if (data.hasOwnProperty(prop)) {
serializeArr.push(encodeURIComponent(prop) + '=' + encodeURIComponent(data[prop]));
}
}
return serializeArr.join('&');
}();
} else if (typeof data === 'string') {
data = data;
} else {
data = null;
}
}
var ifAsync = (options && options.async && options.async === false) ? false : true;
try {
xhr.open(method, url, ifAsync);
// defining onload, onprogress, error and withCredentials
(function() {
for (var prop in options) {
if (options.hasOwnProperty(prop)) {
if (prop === 'onload') {
xhr.onload = function() {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
options[prop].call(xhr, xhr.responseText, xhr.status, xhr);
} else {
console.log('load event -- Request was unsuccessful: ' + xhr.status);
}
};
} else if (prop === 'onprogress' || prop === 'ontimeout' || prop === 'onerror' || prop === 'onabort' || prop === 'onloadstart' || prop === 'onloadend') {
xhr[prop] = function(e) {
options[prop].call(xhr, e, xhr.responseText, xhr.status, xhr);
}
} else if (prop === 'timeout' || prop === 'withCredentials') {
xhr[prop] = options[prop];
} else if (prop === 'overrideMimeType') {
xhr.overrideMimeType(options[prop]);
} else if (prop === 'requestHeader') {
for (var header in options[prop]) {
if (options[prop].hasOwnProperty(header)) {
xhr.setRequestHeader(header, options[prop][header]);
}
}
} else if (prop === 'upload') {
// 使用 Ajax 上传数据的状态事件回调函数,可用 upload.onprogress 实现上传进度条,当然需要服务器支持返回上传进度
for (var uploadEvent in options[prop]) {
if (options[prop].hasOwnProperty(uploadEvent)) {
xhr.upload[uploadEvent] = options[prop][uploadEvent];
}
}
}
}
}
})();
xhr.send(data);
} catch(e) {
console.error('可能由于跨域限制,导致无法发起 Ajax 请求。');
xhr = null;
}
return xhr;
}
Ajax.get = function (url, callback, data, options) {
if (options) {
options.method = 'get';
} else {
options = {
method: 'get'
}
}
return Ajax(url, callback, data, options);
};
// 如果使用 POST 上传的是文本数据,请在 options 内设置 {requestHeader: {'Content-Type': 'application/x-www-form-urlencoded'}}
Ajax.post = function (url, callback, data, options) {
if (options) {
options.method = 'post';
} else {
options = {
method: 'post'
}
}
data = data ? data : '';
if (typeof data === 'string' || data.constructor === Object) {
if (options.requestHeader) {
options.requestHeader['Content-Type'] = 'application/x-www-form-urlencoded';
} else {
options.requestHeader = {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
}
return Ajax(url, callback, data, options);
};
Ajax.getJSON = function (url, callback, data, options) {
var newCallback = function (responseText, status, xhr) {
try {
var responseJSONObj = JSON.parse(responseText);
if (callback) {
callback(responseJSONObj, status, xhr);
} else {
console.log(xhr);
}
} catch(e) {
console.error('数据不符合要求,无法转为 JSON 对象!请确保接口返回数据为 JSON 格式。');
}
};
return Ajax(url, newCallback, data, options);
}
return Ajax;
})();
// 所有事件与callback都接受三个参数:responseText, status, xhr
// var callback = function(responseText, status, xhr) {
// //...
// };
// var options = {
// method: 'get',
// async: false,
// timeout: 2000,
// ontimeout: ontimeout,
// onerror: onerror,
// onabort: onabort,
// onprogress: onprogress,
// onload: onload,
// onloadstart: onloadstart,
// onloadend: onloadend,
// onprogress: onprogress,
// withCredentials: true,
// requestHeader: {
// xxx: yyy,
// ...
// },
// upload: {
// onloadstart: xxx
// onloadend: xxx
// onprogress: xxx
// }
// //...
// };
// 如果使用 POST 上传的是文本数据,请在 options 内设置 {requestHeader: {'Content-Type': 'application/x-www-form-urlencoded'}}
// Ajax(/* ... */);
// new Ajax(/* ... */);
// Ajax.get(/* ... */);
// Ajax.post(/* ... */);
// Ajax.getJSON(/* ... */));
@xiaoxintiaoda

This comment has been minimized.

Copy link

@xiaoxintiaoda xiaoxintiaoda commented Nov 7, 2017

onerror和ontimeout 应该如何定义呢,我写的

 var options = {
    method: 'get',
    async: false,
    timeout: 2000,
    ontimeout: function() {
        showAlterMsg('网络状况不佳,请重试');
    },
    onerror: function () {
        showAlterMsg('请求错误,请重试');
    }
};

每次都直接执行了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment