axios使用:https://juejin.cn/post/7034827130701611016

    手写axios核心代码:https://juejin.cn/post/6856706569263677447

    1. // 创建 axios 类
    2. class Axios {
    3. constructor () {
    4. // 拦截器
    5. this.interceptors = {
    6. request: new InterceptorsManage,
    7. response: new InterceptorsManage
    8. }
    9. }
    10. request(config) {
    11. // 拦截器和请求组装队列
    12. let chain = [ this.sendAjax.bind(this), undefined ] // 成对出现的,失败回调暂时不处理
    13. // 请求拦截
    14. this.interceptors.request.handlers.forEach(interceptor => {
    15. chain.unshift(interceptor.fullfield, interceptor.rejected)
    16. })
    17. // 响应拦截
    18. this.interceptors.response.handlers.forEach(interceptor => {
    19. chain.push(interceptor.fullfield, interceptor.rejected)
    20. })
    21. // 执行队列,每次执行一对,并对promise赋最新的值
    22. let promise = Promise.resolve(config)
    23. while(chain.length > 0) {
    24. promise = promise.then(chain.shift(), chain.shift())
    25. }
    26. return promise
    27. }
    28. // 封装ajax
    29. sendAjax(config) {
    30. return new Promise(resolve => {
    31. const { url = '', method = 'get', data = {} } = config
    32. // 发送 ajax 请求
    33. const xhr = new XMLHttpRequest()
    34. xhr.open(method, url, true)
    35. xhr.onload = function () {
    36. // resolve(xhr.response)
    37. try {
    38. // 将结果转为json对象
    39. resolve(JSON.parse(xhr.response))
    40. } catch (err) {
    41. resolve(xhr.response)
    42. }
    43. }
    44. xhr.send(data)
    45. })
    46. }
    47. }
    48. // 定义get,post...方法,挂在到Axios原型上
    49. const methodsArr = ['get', 'post', 'delete', 'put', 'patch', 'options', 'head']
    50. methodsArr.forEach(met => {
    51. Axios.prototype[met] = function() {
    52. // 处理单个方法
    53. if(['get', 'delete', 'head', 'options'].includes(met)) {
    54. // 2个参数(url[, config])
    55. return this.request({
    56. method: met,
    57. url: arguments[0],
    58. ...arguments[1] || {}
    59. })
    60. } else {
    61. // 3个参数(url[,data[,config]])
    62. return this.request({
    63. method: met,
    64. url: arguments[0],
    65. data: arguments[1] || {},
    66. ...arguments[2] || {}
    67. })
    68. }
    69. }
    70. })
    71. // 拦截器
    72. class InterceptorsManage {
    73. constructor () {
    74. // 保存回调
    75. this.handlers = []
    76. }
    77. use(fullfield, rejected) {
    78. this.handlers.push({
    79. fullfield,
    80. rejected
    81. })
    82. }
    83. }
    84. // 工具方法,实现将b的方法混入a
    85. const utils = {
    86. extend(a, b, context) {
    87. for (let key in b) {
    88. if (b.hasOwnProperty(key)) {
    89. if (typeof b[key] === 'function') {
    90. a[key] = b[key].bind(context)
    91. } else {
    92. a[key] = b[key]
    93. }
    94. }
    95. }
    96. }
    97. }
    98. // 最终导出axios的方法,即实例的request方法
    99. function CreateAxiosFn () {
    100. let axios = new Axios()
    101. let req = axios.request.bind(axios)
    102. // 混入方法,将Axios.prototype上的方法搬运到request上
    103. utils.extend(req, Axios.prototype, axios)
    104. // 将axios上的拦截器挂载到request上
    105. utils.extend(req, axios)
    106. return req
    107. }
    108. // 得到最后的全局变量axios
    109. let axios = CreateAxiosFn()