Last active
March 23, 2020 07:06
-
-
Save yangfch3/4ca039fbaa492b1061a22fdbef4ab367 to your computer and use it in GitHub Desktop.
ajax 请求封装
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(/* ... */)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
onerror和ontimeout 应该如何定义呢,我写的
每次都直接执行了