axios:一款基于PROMISE设计模式封装的AJAX库(JQ中的AJAX就是最普通的AJAX库,没有基于PROMISE管理)
// 使用方法
axios.get([URL],[OPTIONS]);
axios.get();
axios.delete();
axios.head();
axios.post([URL],[DATA],[OPTIONS]):DATA通过请求主传递给服务器的内容
axios.post();
axios.put();
常用的参数配置
- OPTIONS
- baseURL:基础的URL路径
- transformRequest:处理请求参数(对POST系列有作用)
- transformResponse:把返回的结果进行处理
- headers:设置请求头
- params:GET系列请求传递给服务器的内容(会把PARAMS中的内容拼接为X-WWW-FORM-URLENCODED这种格式,基于URL问号传参传递给服务器)
- paramsSerializer:传递参数的序列化
- timeout:超时时间
- withCredentials:跨域请求中是否允许携带凭证
- responseType:预设服务器返回结果的格式,默认是JSON,支持BUFFER/TEXT/S> TREAM/DOCUMENT...
- validateStatus:AXIOS本身只有在HTTP状态码以2开头的时候才认为是成功,> 其余都认为是失败状态,当然我们可以自己来设置,基于validateStatus这个来修改> */
//=>执行axios.xxx()都会返回一个PROMISE实例,AJAX请求成功会把实例的状态改为FULFILLED,请求失败状态改为REJECTED;并且获取的结果或者错误原因作为PROMISE的VALUE
axios.get('http://127.0.0.1:5500/json/data2.json', {
headers: {
AAA: encodeURIComponent('哈喽')
},
params: {
lx: 1,
from: 'WX'
}
}).then(result => {
//=>result:从服务器获取的结果
/*
* CONFIG:我们自己配置的选项信息
* DATA:存储的是响应主体内容
* HEADERS:存储响应头的信息
* REQUEST:AJAX实例
* STATUS:响应状态码
* STATUS-TEXT:状态码的描述
*/
return result.data;
}).catch(reason => {
console.log(reason);
throw new Error(reason);
}).then(data => {
//=>data:从服务器获取的响应主体内容
console.log(data);
});
//==========
axios.post('http://127.0.0.1:5500/json/data2.json', {
lx: 1,
from: 'WX'
}, {
headers: {
AAA: encodeURIComponent('哈哈哈')
},
transformRequest: function (data) {
if (!data) return data;
let str = ``;
for (let key in data) {
if (!data.hasOwnProperty(key)) break;
str += `&${key}=${data[key]}`;
}
return str.substring(1);
}
}).then(result => {
return result.data;
}).catch(reason => {
throw new Error(reason);
}).then(data => {
console.log(data);
});
默认配置项
/* 在使用AXIOS之前,我们一般都需要配置默认的配置项 */
// 1.基础URL,后期再发送请求的时候,URL请求地址最前面的公共部分就不需要再写了
axios.defaults.baseURL = "http://127.0.0.1:5500";
// 2.跨域请求中允许携带资源凭证(例如COOKIE信息)
axios.defaults.withCredentials = true;
// 3.设置请求头:POST系列中,我们传递给服务器数据的格式一般以x-www-form-urlencoded格式为主
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
// 4.设置请求拦截器(只对POST系列有用):把基于请求主体传递给服务器的内容进行拦截,把内容格式变为x-www-form-urlencoded这种格式,再传递给服务器
axios.defaults.transformRequest = function (data) {
if (!data) return data;
let str = ``;
for (let key in data) {
if (!data.hasOwnProperty(key)) break;
str += `&${key}=${data[key]}`;
}
return str.substring(1);
};
// 5.设置响应拦截器:[成功状态]把从服务器获取的结果中的响应主体信息获取到即可,[失败状态]手动把错误信息抛出异常
axios.interceptors.response.use(function (response) {
return response.data;
}, function (error) {
throw new Error(error);
});
// 6.配置什么才算成功(把PROMISE状态改为FULFILLED)
axios.defaults.validateStatus = function (status) {
return /^(2|3)\d{2}$/.test(status);
}
// 使用
axios.get('/json/data2.json').then(data => {
console.log(data);
}).catch(reason => {
console.log(reason);
});
//=>Promise.all
let promise1 = Promise.resolve(100);
let promise2 = Promise.resolve(200);
axios.all([promise1, promise2]).then(results => {
let [val1, val2] = results;
console.log(val1, val2);
});
// =>
axios.all([promise1, promise2]).then(axios.spread(function (val1, val2) {
//=>axios.spread:把基于axios.all获取的结果一项项的单独获取到
console.log(val1, val2);
}))
封装一个伟大的axios库
/*
* 支持的功能
* 1.支持全局默认配置项 _ajax.defaults.xxx=xxx
* 2.发送请求_ajax.get/post...
* 3.每一次请求都会返回PROMISE实例,基于PROMISE设计模式进行管理
* 4.支持_ajax.all
*/
~ function () {
//=>发送AJAX请求,且基于PROMISE进行管理
class MyAjax {
constructor(url, options) {
this.url = url;
this.options = options;
return this.init();
}
//=>发送AJAX请求(基于PROMISE来管理)
init() {
let {
url,
options: {
baseURL,
withCredentials,
headers,
transformRequest,
transformResponse,
validateStatus,
params,
data,
cache,
method
}
} = 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(method)) {
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 (cache === false) {
url += `${url.indexOf('?')===-1?'?':'&'}_=${Math.random()}`;
}
}
xhr.open(method, 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]));
}
}
//=>请求拦截器:请求主体传递信息的拦截
if (/^(POST|PUT)$/i.test(method)) {
typeof transformRequest === 'function' ? data = transformRequest(data) : null;
} else {
data = null;
}
xhr.send(data);
}).then(...transformResponse);
}
}
//=>创建_ajax管理调用
function _init(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: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: function (data) {
if (!data) return data;
let result = ``;
for (let attr in data) {
if (!data.hasOwnProperty(attr)) break;
result += `&${attr}=${data[attr]}`;
}
return result.substring(1);
},
transformResponse: [function onFulfilled(response) {
return response.data;
}, function onRejected(reason) {
return Promise.reject(reason);
}],
validateStatus: function (status) {
return /^(2|3)\d{2}$/.test(status);
},
//=>请求配置项
params: {},
data: {},
cache: true
};
_ajax.all = function all(promiseArr = []) {
return Promise.all(promiseArr);
};
["get", "delete", "head", "options"].forEach(item => {
_ajax[item] = function (url, options = {}) {
options.method = item;
return new MyAjax(url, _init(options));
};
});
["post", "put"].forEach(item => {
_ajax[item] = function (url, data = {}, options = {}) {
//=>把DATA也放到配置项目
options.data = data;
options.method = item;
return new MyAjax(url, _init(options));
};
});
window._ajax = _ajax;
}();