简化的原生ajax
/*
*
* path: seaAjax.js
* author: eric_wang
* date: 2014/10/22
*/
define(function(require,exports,module){
var handpay=handpay||{"version":"v.1.0.0"};
/**
* @namespace handpay.ajax 对XMLHttpRequest请求的封装
* @property success 请求失败的全局事件,function(String responseText,XMLHttpRequest xhr)
* @property error 请求失败的全局事件,function(XMLHttpRequest xhr)
* @property before 请求发送前触发的全局事件,function(XMLHttpRequest xhr)
*/
handpay.ajax = handpay.ajax || {};
/**
* 发送一个ajax请求
* @name handpay.ajax.request
* @function
* @grammar handpay.ajax.request(url[, options])
* @param {string} url 发送请求的url
* @param {Object} [options] 发送请求的选项参数
* @config {String} [method] 请求发送的类型。默认为GET
* @config {String} [dataType] 请求发送的类型。默认为GET
* @config {Boolean} [async] 是否异步请求。默认为true(异步)
* @config {Boolean} [cacheable] 是否缓存请求。默认为true(缓存)
* @config {String} [data] 需要发送的数据。
* @config {Object} [headers] 要设置的http request header
* @config {String} [username] 用户
* @config {String} [password] 密码
* @config {Function} [success] 请求成功时触发,function(string responseText,XMLHttpRequest xhr)
* @config {Function} [error] 请求失败时触发,function(XMLHttpRequest xhr)
* @config {Function} [before] 发送请求之前触发,function(XMLHttpRequest xhr)
* @config {Boolean} [noCache] 是否需要缓存,默认为true(缓存)
* @meta standard
* @see handpay.ajax.get,handpay.ajax.post,handpay.ajax.form
*
* @returns {XMLHttpRequest} 发送请求的XMLHttpRequest对象
*/
handpay.ajax.request=function(url,options){
options = options || {};
var data = options.data || "";
var async = !(options.async === false);// 是否异步请求。默认为true(异步)
var cacheable = !(options.async === false);
var username = options.username || "";
var password = options.password || "";
var method = (options.type || "GET").toUpperCase();
var dataType = (options.dataType || "HTML").toUpperCase();
var headers = options.headers || {};
var success = options.success || "";
var error = options.error || "";
var before = options.before || "";
var jsonp=options.jsonp || "jsonpcallback"; //jsonp的函数名称
var jsonpCallback=options.jsonp||"";
var charset=options.charset||"UTF-8";
var xhr;
/**HTML转义
* @param {string} [str] 需要转义的字符串
*/
function escape(str){
return str
.replace(/&/g,'&')
.replace(/</g,'<')
.replace(/>/g,'>')
.replace(/"/g,'"')
.replace(/'/g,''');
}
function firedEvent(callback){
switch(dataType){
case "TEXT":
if(callback){
callback(escape(xhr.responseText),xhr);
}
break;
case "JSON":
if(callback){
callback(parseJson(xhr.responseText),xhr);
}
break;
case "HTML":
default:
if(callback){
callback(xhr.responseText,xhr);
}
}
}
function parseJson(str){
if(typeof(str)==="object"){
return str;
}
if(JSON){
try{
return JSON.parse(str);
}catch(e){
return (new Function("return "+str))();
}
}else{
return (new Function("return "+str))();
}
}
//状态报告
function reportStatus(){
if (xhr.readyState == 4) {
var stat = xhr.status;
if (stat == 200) {
firedEvent(success);
} else {
// http://www.never-online.net/blog/article.asp?id=261
// case 12002: // Server timeout
// case 12029: // dropped connections
// case 12030: // dropped connections
// case 12031: // dropped connections
// case 12152: // closed by server
// case 13030: // status and statusText are unavailable
// IE error sometimes returns 1223 when it
// should be 204, so treat it as success
if ((stat >= 200 && stat < 300)
|| stat == 304
|| stat == 1223) {
firedEvent(success);
} else {
if(error){
error(xhr.responseText,xhr);
}
}
/*
* NOTE: Testing discovered that for some bizarre reason, on Mozilla, the
* JavaScript <code>XmlHttpRequest.onreadystatechange</code> handler
* function maybe still be called after it is deleted. The theory is that the
* callback is cached somewhere. Setting it to null or an empty function does
* seem to work properly, though.
*
* On IE, there are two problems: Setting onreadystatechange to null (as
* opposed to an empty function) sometimes throws an exception. With
* particular (rare) versions of jscript.dll, setting onreadystatechange from
* within onreadystatechange causes a crash. Setting it from within a timeout
* fixes this bug (see issue 1610).
*
* End result: *always* set onreadystatechange to an empty function (never to
* null). Never set onreadystatechange from within onreadystatechange (always
* in a setTimeout()).
*/
window.setTimeout(
function() {
// 避免内存泄露
xhr.onreadystatechange = new Function();
if (async) {
xhr = null;
}
}, 0);
}
}
}
/**
* 获取XMLHttpRequest对象
*
* @ignore
* @return {XMLHttpRequest} XMLHttpRequest对象
*/
function getXHR() {
if (window.ActiveXObject) {
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
}
}
//execute ajax request
function executeXhr(callback) {
xhr=getXHR();
if(cacheable){
try{
req.setRequestHeader("Cache-Control: no-store, no-cache, must-revalidate");
req.setRequestHeader("Connection","close");
} catch(e){}
}
//
var urlWithParam = url.split("?");//split the url in two parts
var urlPrefix = urlWithParam[0];//the url
var arg = urlWithParam[1];//the arguments
if(method == "POST") {//若为post请求提交则修改url值
url=urlPrefix;
}
if (username) {
xhr.open(method, url, async, username, password);
} else {
xhr.open(method, url, async);
}
if (async) {
xhr.onreadystatechange = callback;
}
xhr.setRequestHeader("Access-Control-Allow-Headers","X-Requested-With");
xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");
for (var key in headers) {
if (headers.hasOwnProperty(key)) {
xhr.setRequestHeader(key, headers[key]);
}
}
if(before){
before.call(this,xhr);
}
if(method == "POST") {
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(arg);
} else {
xhr.send();
}
if (!async) {
if(callback){
callback.call(this);
}
}
}
function loadScript(callback){
var head = document.head ||document.getElementsByTagName("head")[0]|| document.documentElement;
var script = document.createElement("script");
script.async = true;
//if ( s.scriptCharset ) {
script.charset = charset;
//}
script.src =url;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function( _, isAbort) {
if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
// Remove the script
if ( script.parentNode ) {
script.parentNode.removeChild( script );
}
// Dereference the script
script = null;
// Callback if not abort
if ( !isAbort ) {
}else{
if(error){
error();
}
}
}
};
if(before){
jsonpFired(before);
}
if(success){
jsonpFired(success);
}
// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
// Use native DOM manipulation to avoid our domManip AJAX trickery
head.insertBefore( script, head.firstChild );
//}
}
//jsonp 数据获取
function jsonpFired(callback){
//console.log(" window."+jsonpCallback+"=function(data){data=(new Function('return data'))();callback(data)}");
var fired=new Function("callbackfunction","parseJsonFun"," window."+jsonpCallback+"=function(data){data=parseJsonFun(data);callbackfunction(data);}");
fired(callback,parseJson);
}
(function(){
var callback = reportStatus;//default alert
if(data||dataType==="JSONP"){
if(url.indexOf("?")==-1){
url=url+"?";
}else{
url+="&";
}
if(dataType==="JSONP"){
if(!jsonpCallback){// jsonpCallback 参数为空或者没传的时候 重新生成函数名称
jsonpCallback="handpayAjax"+(new Date().getTime());
}
url+=jsonp+"="+jsonpCallback+"&";
}
if(data){
try{
if(typeof(data)==="object"){ //如果data参数是json对象 就转为参数的链式结构
for(var i in data){
if(data.hasOwnProperty(i)){
url+=i+"="+data[i]+"&";
}
}
if(!cacheable){
url+="t"+(new Date().getTime())+"=v1&";
}
url=url.substring(0,url.length-1);
}
}catch(e){
return null;
}
}
}
/*encode URL with Chinese*/
url = encodeURI(url);
//alert(url);
//execute the remote method
if(dataType==="JSONP"){
loadScript(callback);
}else{
executeXhr(callback);
}
})();
};
/**
* 发送一个post请求
* @name handpay.ajax.post
* @function
* @grammar handpay.ajax.post(url, data[, onsuccess])
* @param {string} url 发送请求的url地址
* @param {string} data 发送的数据
* @param {Function} [onsuccess] 请求成功之后的回调函数,function(XMLHttpRequest xhr, string responseText)
* @meta standard
* @see handpay.ajax.get,handpay.ajax.request
*
* @returns {XMLHttpRequest} 发送请求的XMLHttpRequest对象
*/
handpay.ajax.post = function (url, data, success) {
var options={};
options.method="POST";
options.data=data;
options.success=success;
return handpay.ajax.request(
url, options
);
};
/**
* 发送一个get请求
* @name handpay.ajax.get
* @function
* @grammar handpay.ajax.get(url[, onsuccess])
* @param {string} url 发送请求的url地址
* @param {Function} [success] 请求成功之后的回调函数,function(string responseText,XMLHttpRequest xhr)
* @meta standard
* @see handpay.ajax.post,handpay.ajax.request
*
* @returns {XMLHttpRequest} 发送请求的XMLHttpRequest对象
*/
handpay.ajax.get = function (url,data,success) {
var options={};
options.method="GET";
options.data=data;
options.success=success;
return handpay.ajax.request(url,options);
};
/**
* 将一个表单用ajax方式提交
* @name handpay.ajax.form
* @function
* @grammar handpay.ajax.form(form[, options])
* @param {HTMLFormElement} form 需要提交的表单元素
* @param {Object} [options] 发送请求的选项参数
* @config {Boolean} [async] 是否异步请求。默认为true(异步)
* @config {String} [username] 用户
* @config {String} [password] 密码
* @config {Object} [headers] 要设置的http request header
* @config {Function} [replacer] 对参数值特殊处理的函数,replacer(string value, string key)
* @config {Function} [before] 发送请求之前触发,function(XMLHttpRequest xhr)
* @config {Function} [success] 请求成功时触发,function(string responseText,XMLHttpRequest xhr)
* @config {Function} [error] 请求失败时触发,function(XMLHttpRequest xhr)
* @see handpay.ajax.request
*
* @returns {XMLHttpRequest} 发送请求的XMLHttpRequest对象
*/
handpay.ajax.form = function (form, options) {
options = options || {};
var elements = form.elements,
len = elements.length,
method = form.getAttribute('method'),
url = form.getAttribute('action'),
replacer = options.replacer || function (value, name) {
return value;
},
sendOptions = {},
data = [],
i, item, itemType, itemName, itemValue,
opts, oi, oLen, oItem;
/**
* 向缓冲区添加参数数据
* @private
*/
function addData(name, value) {
data.push(name + '=' + value);
}
// 复制发送参数选项对象
for (i in options) {
if (options.hasOwnProperty(i)) {
sendOptions[i] = options[i];
}
}
for (i = 0; i < len; i++) {
item = elements[i];
itemName = item.name;
// 处理:可用并包含表单name的表单项
if (!item.disabled && itemName) {
itemType = item.type;
itemValue = item.value;
switch (itemType) {
// radio和checkbox被选中时,拼装queryString数据
case 'radio':
case 'checkbox':
if (!item.checked) {
break;
}
// 默认类型,拼装queryString数据
case 'textarea':
case 'text':
case 'password':
case 'hidden':
case 'select-one':
addData(itemName, replacer(itemValue, itemName));
break;
// 多行选中select,拼装所有选中的数
case 'select-multiple':
opts = item.options;
oLen = opts.length;
for (oi = 0; oi < oLen; oi++) {
oItem = opts[oi];
if (oItem.selected) {
addData(itemName, replacer(oItem.value, itemName));
}
}
break;
}
}
}
// 完善发送请求的参数选项
sendOptions.data = data.join('&');
sendOptions.method = form.getAttribute('method') || 'POST';
// 发送请
return handpay.ajax.request(url, sendOptions);
};
module.exports=handpay.ajax;
});
相关推荐
结束数据方法的参数,该如何定义?-- 集合为自定义实体类中的结合属性,有几个实体类,改变下标就行了。<input id="add" type="button" value="新增visitor&quo