[关闭]
@jsongao98 2021-04-24T12:17:46.000000Z 字数 3388 阅读 95

axios

工具


jq纯回调方式封装ajax(XHR),所以需要先把callback写好再请求
axios基于promise来封装XHR,链式

特性:

从浏览器创建XHR,node.js创建http请求
返回promise对象,支持Promise API,并发请求promise.all
拦截请求和响应,支持取消请求
转换请求数据和响应数据,自动转换JSON数据
客户端支持防御XSRF

promise链,封装:

axios返回一个promise对象,response.status如果是200-300,则该promise对象的state为resolved,执行then。如果是400,404等,则执行catch。有时候我们需要对不同的状态码进行不同操作,(细分状态码,axios promise只分成功失败),所以一般对axios再进行封装。

axios API:

  • axios(config):

    1. axios({
    2. method:'get',
    3. url:'http://bit.ly/2mTM3nY',
    4. responseType:'stream'
    5. data:...,//post请求是data为请求正文
    6. params:...,//get请求不需要请求正文(request payload)
    7. })
    8. .then(function(response) {
    9. response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
    10. });

    axios(url[,config])默认get方法

    也可以这么写:
    axios.request(config)
    axios.get(url[, config])
    axios.delete(url[, config])
    axios.head(url[, config])
    axios.options(url[, config])
    axios.post(url[, data[, config]])
    axios.put(url[, data[, config]])
    axios.patch(url[, data[, config]])

  • 并行请求:
    axios.all()
    axios.spread() 指定接收所有成功数据的回调函数的方法

  • 创建实例:
    axios.create([config])
    用于封装,复用axios

  • 拦截器:
    axios.interceptors.request.use()
    axios.intereptors.response.use()
    移除axios.interceptors.request.eject()
    axios可替换为自定义实例

  • 取消请求:
    axios.Cancel()用于创建取消请求的错误对象
    axios.CancelToken()用于创建取消请求的token对象

    在axios请求配置中使用new操作符调用,传入一个函数参数(包含取消请求的函数),函数将取消请求的函数保存到一个外部变量中。

    axios.isCancel()是否是一个取消请求的错误

  • 请求默认的全局配置:
    axios.defaults.xxx
    baseURL

    难点理解:

  • axios.create([config])
    1). 根据指定配置创建一个新的axios,也就是每个axios都有自己的配置(如果没有自己的配置,你还创建他干啥)
    2). 新axios只是没有取消请求和批量发请求的方法,其他语法都是一样的
    3). 为什么要设计这么个语法?
    假设你的项目很大,后端有多个host,使用一个axios显然不能很好的解决这个问题.
    所以,你需要针对每一个axios对象设置一个baseURL和其他配置属性,也就是使用create语法创建多个不同配置的axios

  • 拦截器函数/ajax请求/请求回调函数的调用顺序(源码)
    1). 调用axios()并不是马上发送ajax请求,需要经历一系列流程
    2). 假如你添加了两个请求拦截器和响应拦截器
    流程: 请求拦截器2 => 请求拦截器1 => ajax请求 => 响应拦截器1 => 响应拦截器2
    为啥请求拦截器先添加后执行,而响应拦截器却先添加先执行?这个问题后面看到源码便一目了然,莫方~
    3). 此流程是通过promise串联的,请求拦截器传递的是配置config,响应拦截器传递的是response

    1. Axios.prototype.request = function request(config) {
    2. /*eslint no-param-reassign:0*/
    3. // Allow for axios('example/url'[, config]) a la fetch API
    4. if (typeof config === 'string') {
    5. config = arguments[1] || {};
    6. config.url = arguments[0];
    7. } else {
    8. config = config || {};
    9. }
    10. // 合并配置
    11. config = mergeConfig(this.defaults, config);
    12. // 添加method配置, 默认为get
    13. config.method = config.method ? config.method.toLowerCase() : 'get';
    14. /*
    15. 创建用于保存请求/响应拦截函数的数组
    16. 数组的中间放发送请求的函数
    17. 数组的左边放请求拦截器函数(成功/失败)
    18. 数组的右边放响应拦截器函数
    19. */
    20. var chain = [dispatchRequest, undefined];
    21. var promise = Promise.resolve(config);
    22. // 后添加的请求拦截器保存在数组的前面
    23. this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    24. chain.unshift(interceptor.fulfilled, interceptor.rejected);
    25. });
    26. // 后添加的响应拦截器保存在数组的后面
    27. this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    28. chain.push(interceptor.fulfilled, interceptor.rejected);
    29. });
    30. // 通过promise的then()串连起所有的请求拦截器/请求方法/响应拦截器
    31. while (chain.length) {
    32. promise = promise.then(chain.shift(), chain.shift());
    33. }
    34. // 返回用来指定我们的onResolved和onRejected的promise
    35. return promise;
    36. };

    源码分析:
    这个request方法就是axios发送请求的核心方法,在源码中将发送请求分为了几个部分(请求拦截器,发送请求,响应拦截器,响应回调),通过Promise的链式调用将这些部分有机地结合了起来,这样就构成了发送请求拿到数据处理的全部过程。

    • 1.代码开始构建了一个config配置对象,用于第一次执行Promise返回一个成功的promise
    • 2.最核心的数组chain,这个数据中保存了请求拦截器函数,响应拦截器函数和默认就有的发送请求的函数,第一步返回的成功的promise对象,将遍历这个数组逐一执行里面的函数,并返回新的Promise对象
    • 3.往数组中添加请求拦截器函数,依照axios请求的执行顺序,请求拦截器应该在发送请求之前执行,故应该添加在发送请求函数的前面,所以使用的是数组的unshift方法,这个方法意思是头部添加,即后面添加的元素总是在头部
    • 4.往数组中添加请求拦截器函数,依照axios请求的执行顺序,响应拦截器应该在发送请求之后执行,故应该添加在发送请求函数的后面,所以使用的是数组的push方法,这个方法意思是尾部添加,即后面添加的元素总是在尾部
    • 5.promise遍历执行,使用的while循序,使用数组的shift方法每次从中取出两个函数执行(成功回调,失败回调)
    • 6.返回Promise对象,用于执行我们指定的响应数据的回调

  • 取消请求的流程
    1). 配置cancelToken对象
    2). 缓存用于取消请求的cancel函数
    3). 在特定的时机下调用cancel函数
    4). 在error回调中判断,如果error是cancel,做相应处理


  • 总流程图

    此处输入图片的描述

  • 添加新批注
    在作者公开此批注前,只有你和作者可见。
    回复批注