在正式开始axios讲解前,让我们先想想,如何对现有的$.ajax进行简单的封装,就可以直接使用原声Promise了?
1 let axios = function(config){ 2 return new Promise((res, rej) => { 3 4 // 发送ajax请求,一般使用$.ajax() 5 ajax({ 6 ...config, 7 success(data){ 8 res(data); 9 },10 error(e){11 rej(e);12 }13 })14 })15 }
然后就可以 axios(...).then().catch()的使用了。
通过上面简单代码,我们就已经清楚了axios基本的实现原理:
内部通过Promise对XHR对象及其事件进行封装,
然后外部就可以通过操作Promise的方式进行异步处理了。
是不是很简单,那接下来就开始我们正式的讲解吧
1 /** 2 * 2,为url、data、headers添加统一处理方法 3 */ 4 let axios = function(config) { 5 return new Promise((res, rej) => { 6 7 // 为url、data、headers添加统一处理方法 8 // (此处只为展示大概架构,暂时不必关心方法的实现,下面会做详细介绍) 9 let { url, method, data, params, headers } = config;10 url = buildURL(combineURLs(config.baseURL, url), params);11 headers = merge(headers.common, headers);12 data = transformData(data, headers);13 14 // 发送ajax请求,一般使用$.ajax()15 ajax({16 ...config,17 url,18 data,19 headers,20 success(data) {21 res(data);22 },23 error(e) {24 rej(e);25 }26 })27 })28 }
/** * 3,放弃ajax方法,对原生XHR进行简单封装 */let axios = function (config) { // 默认配置项 let defaultConfig = { method: ‘get‘, responseType: ‘json‘, timeout: 0, } return new Promise((res, rej) => { config = merge(defaultConfig, config); // 为url、data、headers添加统一处理方法 let { url, method, data, params, headers } = config; url = buildURL(combineURLs(config.baseURL, url), params); headers = merge(headers.common, headers); data = transformData(data, headers); // 创建xhr实例 var xhr = new XMLHttpRequest(); xhr.open(method, url); xhr.responseType = config.responseType; xhr.timeout = config.timeout; request.addEventListener(‘progress‘, config.onDownloadProgress); xhr.onload = function () { // 先要判断 xhr.status逻辑 res(xhr.response) }; xhr.onerror = function () { rej(‘Network Error‘) }; xhr.ontimeout = function handleTimeout() { rej(‘timeout‘); }; xhr.send(data); })}
1 /** 2 * 4,改用class来实现一个简单的axios 3 */ 4 class Axios { 5 constructor(instanceConfig){ 6 this.defaults = instanceConfig; 7 } 8 request(config){ 9 10 this.config = {11 ...this.defaults,12 ...config,13 }14 this.dispatchRequest();15 16 }17 dispatchRequest(){18 // 为url、data、headers添加统一处理方法19 let { url, method, data, params, headers } = this.config;20 url = buildURL(combineURLs(config.baseURL, url), params);21 headers = merge(headers.common, headers);22 data = transformData(data, headers);23 24 // 创建xhr实例25 var xhr = new XMLHttpRequest();26 xhr.open(method, url);27 xhr.responseType = config.responseType;28 xhr.timeout = config.timeout;29 request.addEventListener(‘progress‘, config.onDownloadProgress);30 xhr.onload = function () {31 // 先要判断 xhr.status逻辑32 res(xhr.response)33 };34 xhr.onerror = function () {35 rej(‘Network Error‘)36 };37 xhr.ontimeout = function handleTimeout() {38 rej(‘timeout‘);39 };40 xhr.send(data);41 }42 }43 44 // 默认配置项45 let defaultConfig = {46 method: ‘get‘,47 responseType: ‘json‘,48 timeout: 0,49 }50 51 // 创建axios实例,使axios具有 axios()直接调用方式和 axios.request()调用方式52 function createInstance(defaultConfig){53 let context = new Axios(defaultConfig);54 let instance = Axios.prototype.request.bind(context);55 extend(instance, Axios.prototype, context);56 extend(instance, context);57 }58 59 let axios = createInstance(defaultConfig);
/** * 5, 添加get、post、put等简写用法 */class Axios { constructor(instanceConfig) { this.defaults = instanceConfig; } request(config) { this.config = { ...this.defaults, ...config, } this.dispatchRequest(); } dispatchRequest() { // 为url、data、headers添加统一处理方法 let { url, method, data, params, headers } = this.config; url = buildURL(combineURLs(config.baseURL, url), params); headers = merge(headers.common, headers); data = transformData(data, headers); // 创建xhr实例 var xhr = new XMLHttpRequest(); xhr.open(method, url); xhr.responseType = config.responseType; xhr.timeout = config.timeout; request.addEventListener(‘progress‘, config.onDownloadProgress); xhr.onload = function () { // 先要判断 xhr.status逻辑 res(xhr.response) }; xhr.onerror = function () { rej(‘Network Error‘) }; xhr.ontimeout = function handleTimeout() { rej(‘timeout‘); }; xhr.send(data); }}let noDataMethods = [‘delete‘, ‘get‘, ‘head‘, ‘options‘];let hasDataMethods = [‘post‘, ‘put‘, ‘patch‘];for (const method of noDataMethods) { Axios.prototype[method] = function (url, config = {}){ return this.request({ ...config, method: method, url: url, }); } }for (const method of hasDataMethods) { Axios.prototype[method] = function (url, data, config = {}) { return this.request({ ...config, method: method, url: url, data, }); }}// 默认配置项let defaultConfig = { method: ‘get‘, responseType: ‘json‘, timeout: 0,}// 创建axios实例,使axios具有 axios()直接调用方式和 axios.request()调用方式function createInstance(defaultConfig) { let context = new Axios(defaultConfig); let instance = Axios.prototype.request.bind(context); extend(instance, Axios.prototype, context); extend(instance, context);}let axios = createInstance(defaultConfig);
1 /** 2 * 6,增加拦截功能,在请求前修改配置和数据,在请求后修改返回结果 3 */ 4 class Axios { 5 constructor(instanceConfig) { 6 this.defaults = instanceConfig; 7 } 8 request(config) { 9 10 this.config = {11 ...this.defaults,12 ...config,13 }14 var chain = [dispatchRequest, undefined];15 var promise = Promise.resolve(config);16 17 }18 dispatchRequest(config) {19 // 为url、data、headers添加统一处理方法20 let { url, method, data, params, headers } = config;21 url = buildURL(combineURLs(config.baseURL, url), params);22 headers = merge(headers.common, headers);23 data = transformData(data, headers);24 25 // 创建xhr实例26 var xhr = new XMLHttpRequest();27 xhr.open(method, url);28 xhr.responseType = config.responseType;29 xhr.timeout = config.timeout;30 request.addEventListener(‘progress‘, config.onDownloadProgress);31 xhr.onload = function () {32 // 先要判断 xhr.status逻辑33 res(xhr.response)34 };35 xhr.onerror = function () {36 rej(‘Network Error‘)37 };38 xhr.ontimeout = function handleTimeout() {39 rej(‘timeout‘);40 };41 xhr.send(data);42 }43 }44 let noDataMethods = [‘delete‘, ‘get‘, ‘head‘, ‘options‘];45 let hasDataMethods = [‘post‘, ‘put‘, ‘patch‘];46 for (const method of noDataMethods) {47 Axios.prototype[method] = function (url, config = {}) {48 return this.request({49 ...config,50 method: method,51 url: url,52 });53 }54 }55 for (const method of hasDataMethods) {56 Axios.prototype[method] = function (url, data, config = {}) {57 return this.request({58 ...config,59 method: method,60 url: url,61 data,62 });63 }64 }65 66 // 默认配置项67 let defaultConfig = {68 method: ‘get‘,69 responseType: ‘json‘,70 timeout: 0,71 }72 73 // 创建axios实例,使axios具有 axios()直接调用方式和 axios.request()调用方式74 function createInstance(defaultConfig) {75 let context = new Axios(defaultConfig);76 let instance = Axios.prototype.request.bind(context);77 extend(instance, Axios.prototype, context);78 extend(instance, context);79 }80 81 let axios = createInstance(defaultConfig);
// 其他:
// 撤销请求abort
// 添加 xsrf header
未完待续...