先说一下平时工作的情况:
日常的工作业务中,与后端数据交互只用了两种形式,GET
和POST
,写业务代码的时候传的参数都是对象格式{name:'jason',age:27}
,一般都是这样写:
Http.get('api/userCenter/bookList.json',{ date: '2010',lang: 'en' }).then(function(res) { console.log(res); }) Http.post('api/userCenter/login.json',{ mobile: 13821863666,psd: 123123 }).then(function(res) { console.log(this); })
GET
传输时,需要把对应的参数拼接在URL的后面;POST
传输时,send的数据格式也主要只用到了以下三种:
Content-Type: application/x-www-form-urlencoded
,send(data)中的data数据格式为"name=jason&age=27"
,此时需要序列化参数对象Content-Type: application/json
,send(data)中的data数据格式为"{"mobile":13821863666,"psd":123123}"
,此时需要用JSON.stringify()
把参数对象转换成json字符串使用
FormData
对象,直接send(FormDataObj)即可,此时不需要设置Content-Type
我就针对以上这些应用场景对ajax做了简单的封装,代码如下:
// http.js // note:xhr的兼容写法 // function XHR() { // if (window.XMLHttpRequest) return new XMLHttpRequest(); // if (window.ActiveXObject) return new ActiveXObject('Microsoft.XMLHTTP'); // return 'Not support XMLHttpRequest!'; // } // 判断是否为纯对象,比如这种格式 {'name': 'jason'} 是纯对象,函数、数组等则不是 function isPlainObject(obj) { return Object.prototype.toString.call(obj) === '[object Object]'; } // 查询字符串中每个参数的名称和值都必须使用 encodeURIComponent() 进行编码,然后才能放到 URL 的末尾; // 所有名-值对儿都必须由和号 ( & ) 分隔 function addURLParam(url,name,value) { url += (url.indexOf('?') == -1 ? '?' : '&'); url += encodeURIComponent(name) + '=' + encodeURIComponent(value); return url; } /** * Converts an object to x-www-form-urlencoded serialization. * http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/ * @param {Object} obj * @return {String} */ function serialize(obj) { var query = '',value,fullSubName,subName,subValue,innerObj,i; for (name in obj) { value = obj[name]; if (value instanceof Array) { for (i = 0; i < value.length; ++i) { subValue = value[i]; fullSubName = name + '[' + i + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += serialize(innerObj) + '&'; } } else if (value instanceof Object) { for (subName in value) { subValue = value[subName]; fullSubName = name + '[' + subName + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += serialize(innerObj) + '&'; } } else if (value !== undefined && value !== null) query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; } return query.length ? query.substr(0,query.length - 1) : query; } function ajax(type,url,data,contentType) { return new Promise(function(resolve,reject) { var xhr = new XMLHttpRequest(); if (type.toUpperCase() === 'GET' && data) { for (key in data) { if (data.hasOwnProperty(key)) { url = addURLParam(url,key,data[key]); } } } /** post传输,当传FormData类型的数据时,不需要设置Content-Type * 当数据格式为纯对象时 * 默认设置'Content-Type'为'application/x-www-form-urlencoded',对数据进行序列化 * 如果'Content-Type'设置为'application/json',数据直接传json字符串 **/ if (type.toUpperCase() === 'POST' && isPlainObject(data)) { if (!contentType || contentType === 'application/x-www-form-urlencoded') { xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); data = serialize(data); } else { xhr.setRequestHeader('Content-Type','application/json'); data = JSON.stringify(data); } } xhr.open(type,true); xhr.onload = function() { if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) { var res = JSON.parse(xhr.response); resolve(res); } else { reject(xhr.statusText); } }; xhr.timeout = 10000; xhr.ontimeout = function() { reject('链接超时!') }; xhr.onerror = function() { reject('网络错误!'); }; xhr.onabort = function() { reject('请求取消!'); }; xhr.send(type.toUpperCase() === 'GET' ? null : data); // 如果不需要通过请求主体发送数据,则必须传入null,因为这个参数对有些浏览器来说是必需的 }); } export default { get: function(url,data) { return ajax('GET',data); },post: function(url,contentType) { return ajax('POST',contentType); } }
之后就可以在其他文件中使用get
和post
这两个接口:
import Http form 'http' Http.get('api/userCenter/bookList.json',psd: 123123 }).then(function(res) { console.log(this); })
get
的使用形式是Http.get(url,data)
;post
的使用形式是Http.post(url,contentType)
,第三个参数contentType
可选,当设置了对应的值时,http.js会对传入的参数做不同格式化的处理。