-
-
Save chiwent/ea3e8881d15c5c5299aa327490cd6ba4 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(/* ... */)); |
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
<!DOCTYPE html> | |
<html lang="zh-cmn-Hans"> | |
<head> | |
<meta http-equiv="Access-Control-Allow-Origin" content="*"> | |
<meta charset="utf-8"> | |
<meta content="initial-scale=1,maximum-scale=1,user-scalable=no,width=device-width" name="viewport" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> | |
<meta name="renderer" content="webkit"> | |
<meta http-equiv="Cache-Control" content="no-siteapp" /> | |
<title>Hi</title> | |
</head> | |
<body> | |
<input id="upFile" , type="file" value="选择文件" name="upFile"> | |
<br/> | |
<!-- 当然,如果你要考虑兼容性,那么着了可以选择非 progress --> | |
<progress id="progress" value="0"></progress> | |
<button id="button">Start uploading</button> | |
<span id="display"></span> | |
<!-- 见我的 gist 里的 ajax.js --> | |
<script src="./ajax.js"></script> | |
<script> | |
var progressBar = document.getElementById("progress"), | |
loadBtn = document.getElementById("button"), | |
display = document.getElementById("display"); | |
upFile = document.getElementById("upFile"); | |
function upload(data) { | |
// 其他可用于文件上传操作练习的 API:http://malsup.com/jquery/form/file-echo2.php | |
var xhr = new Ajax('https://zinoui.com/demo/progress-bar/upload.php', null, data, { | |
method: 'post', | |
'Content-Type': 'multipart/form-data', | |
// 多余地设置 withCredentials 为 true 可能会造成报错 | |
// withCredentials: true, | |
upload: { | |
onprogress: function(e) { | |
if (e.lengthComputable) { | |
progressBar.max = e.total; | |
progressBar.value = e.loaded; | |
display.innerText = Math.floor((e.loaded / e.total) * 100) + '%'; | |
} | |
}, | |
onloadstart: function(e) { | |
progressBar.value = 0; | |
display.innerText = '0%'; | |
}, | |
onloadend: function(e) { | |
progressBar.value = e.loaded; | |
loadBtn.disabled = false; | |
loadBtn.innerHTML = 'Start uploading'; | |
} | |
} | |
}); | |
} | |
function buildFormData() { | |
var fd = new FormData(); | |
fd.append('file', upFile.files[0]); | |
// for (var i = 0; i < 3000; i += 1) { | |
// fd.append('data[]', Math.floor(Math.random() * 999999)); | |
// } | |
return fd; | |
} | |
loadBtn.addEventListener("click", function(e) { | |
this.disabled = true; | |
this.innerHTML = "Uploading..."; | |
upload(buildFormData()); | |
}); | |
// 服务器端代码 | |
// <?php | |
// header('Access-Control-Allow-Origin: *'); | |
// header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); | |
// foreach($_FILES as $file) { | |
// $n = $file['name']; | |
// $s = $file['size']; | |
// if (is_array($n)) { | |
// $c = count($n); | |
// for ($i=0; $i < $c; $i++) { | |
// echo "<br>uploaded: " . $n[$i] . " (" . $s[$i] . " bytes)"; | |
// } | |
// } | |
// else { | |
// echo "<br>uploaded: $n ($s bytes)"; | |
// } | |
// } | |
// ?> | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment