在正式开始axios讲解前,让我们先想想,如何对现有的$.ajax进行简单的封装,就可以直接使用原声Promise了?  

  1. 1 let axios = function(config){
  2. 2 return new Promise((res, rej) => {
  3. 3
  4. 4 // 发送ajax请求,一般使用$.ajax()
  5. 5 ajax({
  6. 6 ...config,
  7. 7 success(data){
  8. 8 res(data);
  9. 9 },
  10. 10 error(e){
  11. 11 rej(e);
  12. 12 }
  13. 13 })
  14. 14 })
  15. 15 }

然后就可以 axios(…).then().catch()的使用了。

 

通过上面简单代码,我们就已经清楚了axios基本的实现原理:

内部通过Promise对XHR对象及其事件进行封装,

然后外部就可以通过操作Promise的方式进行异步处理了。

 

是不是很简单,那接下来就开始我们正式的讲解吧

 

  1. 1 /**
  2. 2 * 2,为url、data、headers添加统一处理方法
  3. 3 */
  4. 4 let axios = function(config) {
  5. 5 return new Promise((res, rej) => {
  6. 6
  7. 7 // 为url、data、headers添加统一处理方法
  8. 8 // (此处只为展示大概架构,暂时不必关心方法的实现,下面会做详细介绍)
  9. 9 let { url, method, data, params, headers } = config;
  10. 10 url = buildURL(combineURLs(config.baseURL, url), params);
  11. 11 headers = merge(headers.common, headers);
  12. 12 data = transformData(data, headers);
  13. 13
  14. 14 // 发送ajax请求,一般使用$.ajax()
  15. 15 ajax({
  16. 16 ...config,
  17. 17 url,
  18. 18 data,
  19. 19 headers,
  20. 20 success(data) {
  21. 21 res(data);
  22. 22 },
  23. 23 error(e) {
  24. 24 rej(e);
  25. 25 }
  26. 26 })
  27. 27 })
  28. 28 }

 

  1. /**
  2. * 3,放弃ajax方法,对原生XHR进行简单封装
  3. */
  4. let axios = function (config) {
  5. // 默认配置项
  6. let defaultConfig = {
  7. method: 'get',
  8. responseType: 'json',
  9. timeout: 0,
  10. }
  11. return new Promise((res, rej) => {
  12. config = merge(defaultConfig, config);
  13. // 为url、data、headers添加统一处理方法
  14. let { url, method, data, params, headers } = config;
  15. url = buildURL(combineURLs(config.baseURL, url), params);
  16. headers = merge(headers.common, headers);
  17. data = transformData(data, headers);
  18. // 创建xhr实例
  19. var xhr = new XMLHttpRequest();
  20. xhr.open(method, url);
  21. xhr.responseType = config.responseType;
  22. xhr.timeout = config.timeout;
  23. request.addEventListener('progress', config.onDownloadProgress);
  24. xhr.onload = function () {
  25. // 先要判断 xhr.status逻辑
  26. res(xhr.response)
  27. };
  28. xhr.onerror = function () {
  29. rej('Network Error')
  30. };
  31. xhr.ontimeout = function handleTimeout() {
  32. rej('timeout');
  33. };
  34. xhr.send(data);
  35. })
  36. }

 

  1. 1 /**
  2. 2 * 4,改用class来实现一个简单的axios
  3. 3 */
  4. 4 class Axios {
  5. 5 constructor(instanceConfig){
  6. 6 this.defaults = instanceConfig;
  7. 7 }
  8. 8 request(config){
  9. 9
  10. 10 this.config = {
  11. 11 ...this.defaults,
  12. 12 ...config,
  13. 13 }
  14. 14 this.dispatchRequest();
  15. 15
  16. 16 }
  17. 17 dispatchRequest(){
  18. 18 // 为url、data、headers添加统一处理方法
  19. 19 let { url, method, data, params, headers } = this.config;
  20. 20 url = buildURL(combineURLs(config.baseURL, url), params);
  21. 21 headers = merge(headers.common, headers);
  22. 22 data = transformData(data, headers);
  23. 23
  24. 24 // 创建xhr实例
  25. 25 var xhr = new XMLHttpRequest();
  26. 26 xhr.open(method, url);
  27. 27 xhr.responseType = config.responseType;
  28. 28 xhr.timeout = config.timeout;
  29. 29 request.addEventListener('progress', config.onDownloadProgress);
  30. 30 xhr.onload = function () {
  31. 31 // 先要判断 xhr.status逻辑
  32. 32 res(xhr.response)
  33. 33 };
  34. 34 xhr.onerror = function () {
  35. 35 rej('Network Error')
  36. 36 };
  37. 37 xhr.ontimeout = function handleTimeout() {
  38. 38 rej('timeout');
  39. 39 };
  40. 40 xhr.send(data);
  41. 41 }
  42. 42 }
  43. 43
  44. 44 // 默认配置项
  45. 45 let defaultConfig = {
  46. 46 method: 'get',
  47. 47 responseType: 'json',
  48. 48 timeout: 0,
  49. 49 }
  50. 50
  51. 51 // 创建axios实例,使axios具有 axios()直接调用方式和 axios.request()调用方式
  52. 52 function createInstance(defaultConfig){
  53. 53 let context = new Axios(defaultConfig);
  54. 54 let instance = Axios.prototype.request.bind(context);
  55. 55 extend(instance, Axios.prototype, context);
  56. 56 extend(instance, context);
  57. 57 }
  58. 58
  59. 59 let axios = createInstance(defaultConfig);

 

  1. /**
  2. * 5, 添加get、post、put等简写用法
  3. */
  4. class Axios {
  5. constructor(instanceConfig) {
  6. this.defaults = instanceConfig;
  7. }
  8. request(config) {
  9. this.config = {
  10. ...this.defaults,
  11. ...config,
  12. }
  13. this.dispatchRequest();
  14. }
  15. dispatchRequest() {
  16. // 为url、data、headers添加统一处理方法
  17. let { url, method, data, params, headers } = this.config;
  18. url = buildURL(combineURLs(config.baseURL, url), params);
  19. headers = merge(headers.common, headers);
  20. data = transformData(data, headers);
  21. // 创建xhr实例
  22. var xhr = new XMLHttpRequest();
  23. xhr.open(method, url);
  24. xhr.responseType = config.responseType;
  25. xhr.timeout = config.timeout;
  26. request.addEventListener('progress', config.onDownloadProgress);
  27. xhr.onload = function () {
  28. // 先要判断 xhr.status逻辑
  29. res(xhr.response)
  30. };
  31. xhr.onerror = function () {
  32. rej('Network Error')
  33. };
  34. xhr.ontimeout = function handleTimeout() {
  35. rej('timeout');
  36. };
  37. xhr.send(data);
  38. }
  39. }
  40. let noDataMethods = ['delete', 'get', 'head', 'options'];
  41. let hasDataMethods = ['post', 'put', 'patch'];
  42. for (const method of noDataMethods) {
  43. Axios.prototype[method] = function (url, config = {}){
  44. return this.request({
  45. ...config,
  46. method: method,
  47. url: url,
  48. });
  49. }
  50. }
  51. for (const method of hasDataMethods) {
  52. Axios.prototype[method] = function (url, data, config = {}) {
  53. return this.request({
  54. ...config,
  55. method: method,
  56. url: url,
  57. data,
  58. });
  59. }
  60. }
  61. // 默认配置项
  62. let defaultConfig = {
  63. method: 'get',
  64. responseType: 'json',
  65. timeout: 0,
  66. }
  67. // 创建axios实例,使axios具有 axios()直接调用方式和 axios.request()调用方式
  68. function createInstance(defaultConfig) {
  69. let context = new Axios(defaultConfig);
  70. let instance = Axios.prototype.request.bind(context);
  71. extend(instance, Axios.prototype, context);
  72. extend(instance, context);
  73. }
  74. let axios = createInstance(defaultConfig);

 

  1. 1 /**
  2. 2 * 6,增加拦截功能,在请求前修改配置和数据,在请求后修改返回结果
  3. 3 */
  4. 4 class Axios {
  5. 5 constructor(instanceConfig) {
  6. 6 this.defaults = instanceConfig;
  7. 7 }
  8. 8 request(config) {
  9. 9
  10. 10 this.config = {
  11. 11 ...this.defaults,
  12. 12 ...config,
  13. 13 }
  14. 14 var chain = [dispatchRequest, undefined];
  15. 15 var promise = Promise.resolve(config);
  16. 16
  17. 17 }
  18. 18 dispatchRequest(config) {
  19. 19 // 为url、data、headers添加统一处理方法
  20. 20 let { url, method, data, params, headers } = config;
  21. 21 url = buildURL(combineURLs(config.baseURL, url), params);
  22. 22 headers = merge(headers.common, headers);
  23. 23 data = transformData(data, headers);
  24. 24
  25. 25 // 创建xhr实例
  26. 26 var xhr = new XMLHttpRequest();
  27. 27 xhr.open(method, url);
  28. 28 xhr.responseType = config.responseType;
  29. 29 xhr.timeout = config.timeout;
  30. 30 request.addEventListener('progress', config.onDownloadProgress);
  31. 31 xhr.onload = function () {
  32. 32 // 先要判断 xhr.status逻辑
  33. 33 res(xhr.response)
  34. 34 };
  35. 35 xhr.onerror = function () {
  36. 36 rej('Network Error')
  37. 37 };
  38. 38 xhr.ontimeout = function handleTimeout() {
  39. 39 rej('timeout');
  40. 40 };
  41. 41 xhr.send(data);
  42. 42 }
  43. 43 }
  44. 44 let noDataMethods = ['delete', 'get', 'head', 'options'];
  45. 45 let hasDataMethods = ['post', 'put', 'patch'];
  46. 46 for (const method of noDataMethods) {
  47. 47 Axios.prototype[method] = function (url, config = {}) {
  48. 48 return this.request({
  49. 49 ...config,
  50. 50 method: method,
  51. 51 url: url,
  52. 52 });
  53. 53 }
  54. 54 }
  55. 55 for (const method of hasDataMethods) {
  56. 56 Axios.prototype[method] = function (url, data, config = {}) {
  57. 57 return this.request({
  58. 58 ...config,
  59. 59 method: method,
  60. 60 url: url,
  61. 61 data,
  62. 62 });
  63. 63 }
  64. 64 }
  65. 65
  66. 66 // 默认配置项
  67. 67 let defaultConfig = {
  68. 68 method: 'get',
  69. 69 responseType: 'json',
  70. 70 timeout: 0,
  71. 71 }
  72. 72
  73. 73 // 创建axios实例,使axios具有 axios()直接调用方式和 axios.request()调用方式
  74. 74 function createInstance(defaultConfig) {
  75. 75 let context = new Axios(defaultConfig);
  76. 76 let instance = Axios.prototype.request.bind(context);
  77. 77 extend(instance, Axios.prototype, context);
  78. 78 extend(instance, context);
  79. 79 }
  80. 80
  81. 81 let axios = createInstance(defaultConfig);

 

 

 

// 其他:
// 撤销请求abort
// 添加 xsrf header

 

 

未完待续…

 

版权声明:本文为wwwweb原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wwwweb/p/axios.html