/**
* 支持的功能
* 1.支持全局默认配置项
* 2.发送请求_ajax.get/post..
* 3.每一次请求都会返回promise实例,基于promise设计模式管理
* 4.支持_ajax.all
* 5.有实现拦截器这个功能
*/
~function(){
//封装Ajax类
class MyAjax{
constructor(url,options){
this.url = url;
this.options = options
return this.init();
}
//发送ajax请求(基于promise来管理)
init(){
//进行解构
let {
url,
potions: {
baseURl,
withCredentials,
headers,
transformRequest,
transformResponse,
validateStatus,
params,
data,
caches,
methods
}
}=this;
//保证响应拦截器中信息的合法性
!Array.isArray(transformResponse) ? transformResponse = [] : null;
new Array(2).fill(null).forEach((item,index)=>{
typeof transformResponse[index] !== 'function' ? transformResponse[index] = null : null;
})
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest;
//URL的处理
url = baseURl+url;
if(/^(GET|DELETE|HEAD|OPTIONS)$/i.test(methods)){
if(params){
let result = ``;
for(let attr in params){
if(!params.hasOwnProperty(attr)) break;
result = `&${attr}=${params[attr]}`;
}
result = result.substring(1);
url += `${url.indexOf('?')===-1?'?':'&'}${result}`;
}
if(caches===false){
url += `${url.indexOf('?')===-1?'?':'&'}_=${Math.random()}`;
}
}
xhr.open(methods,url);
xhr.onreadystatechange=()=>{
let resultFlag = validateStatus(xhr.status);
if(!resultFlag){
reject({
status:xhr.status,
statusText: xhr.statusText,
request = xhr
});
return;
}
if(xhr.readyState === 4){
//把所有响应头变成键值对方式
let res_headers = {};
xhr.getAllResponseHeaders().split(/\n/).forEach(item=>{
let [key='',value=''] = item.split(':');
if(key.trim()==='')return;
res_headers[key.trim()] = value.trim();
});
resolve({
status: xhr.status,
statusText: xhr.statusText,
request = xhr,
data: JSON.parse(xhr.responseText),
headers : res_headers
});
}
}
// 跨域处理
xhr.withCredentials = withCredentials;
//设置请求头
if(headers){
for(let attr in headers){
if(!headers.hasOwnProperty(attr))break;
xhr.setRequestHeader(attr,encodeURI(headers[attr]))
}
}
//请求拦截器:请求主体传递信息的拦截 对data的处理
if(/^(POST|PUT)$/i.test(methods)){
typeof transformRequest === 'function' ? data = transformRequest(data) : null;
}else{
data = null;
}
xhr.send();
}).then(...transformResponse); //保证在执行自己的then()之前,执行拦截器,在创建完promise实例之后直接设置拦截器的then方法
}
}
function _init(options){
//将_ajax.defaults和函数中的options参数进行匹配合并
/**
* 参数初始化:headers需要特殊处理(把用户options中传递的headers和defaults中的headers进行合并,而不是整体替换),
* 其余的配置项直接用options中的替换defaults中的即可
*
*/
let optionsHeaders = options.headers;
_ajax.defaults.headers = Object.assign(_ajax.defaults.headers,optionsHeaders)
delete options.headers;
return Object.assign(_ajax.defaults,options);
}
function _ajax(){
//创建全局的默认配置
_ajax.defaults = {
baseURl = '',
withCredentials: false, //表示跨域请求时是否需要使用凭证
headers:{},
transformRequest: function (data) {
// `transformRequest` 允许在向服务器发送前,修改请求数据
if(!data) return data;
let str = ``;
//循环data
for(let key in data){
if(!data.hasOwnProperty(key))break;
str = `&${key}=${data[key]}`;
}
return str.substring(1);;
},
transformResponse: [function onFulfilled(response){
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
return response.data;
},function onRejected(reason){
return Promise.reject(reason);
}],
validateStatus: function (status) {
//http的响应状态码
return /^(2|3)\d{2}$/.test(status);
},
//请求配置项
params:{},
data:{},
caches: true
}
["get","delete","head","options"].forEach(item=>{
options.methods = item;
_ajax[item] = function(url,options={}){
return new MyAjax(url,_init(options));
}
});
["post","put"].forEach(item=>{
_ajax[item] = function(url,data={},options={}){
//把data也放到配置项目
options.data = data;
options.methods = item;
return new MyAjax(url,_init(options));
}
})
_ajax.all = function all(promiseArr = []){
return Promise.all(promiseArr);
}
}
window._ajax = _ajax; //对全局暴露_ajax;
}();