axios詳解及封裝一個偉大的axios庫

axios:一款基於PROMISE設計模式封裝的AJAX庫(JQ中的AJAX就是最普通的AJAX庫,沒有基於PROMISE管理)javascript

// 使用方法
axios.get([URL],[OPTIONS]);
axios.get();
axios.delete();
axios.head();

axios.post([URL],[DATA],[OPTIONS]):DATA經過請求主傳遞給服務器的內容
axios.post();
axios.put();
複製代碼

經常使用的參數配置java

  • 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);
}); 
複製代碼

默認配置項ios

/* 在使用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;
}();

複製代碼
相關文章
相關標籤/搜索