Axios 面试题
一、Axios是什么?
Axios是一个基于promise的网络请求库,可用于node.js和浏览器中。它是isomorphic的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生node.js http模块,而在客户端(浏览器端)则使用XMLHttpRequests。
特性
1. 从浏览器创建XMLHttpRequests,从node.js创建http请求
2. 支持promise API
3. 拦截请求和相应,转换请求和相应数据,取消请求,自动转换JSON数据
4. 客户端支持防御XSRF
二、取消请求
Axios支持以fetch API的方式,AbortController取消请求
const controller = new AbortController(); axios.get('/foo/bar',{ signal:controller.signal }).then(res => { console.log(res.data) }) //取消请求 controller.abort()
三、拦截器
在请求或响应被then或catch处理签拦截它们
//添加请求拦截器 axios.interceptors.request.use(config => { //在发送请求之前做些什么 return config },err => { //对请求错误做些什么 return Promise.reject(err) })
//添加响应拦截器 axios.interceptors.response.use(res=>{ //2xx范围的状态码都会触发该函数 //对响应数据做点什么 return response },err=>{ return Promise.reject(err) })
如果你需要稍后移除拦截器,可以这样
const myInterceptor = axios.interceptors.request.use(/*...*/) axios.interceptors.request.reject(myInterceptor);
可以给自定义的axios实例添加拦截器
const instance = axios.create(); instance.interceptors.request.use(/**/)
四、请求失败,重复发送请求
1. 使用 axios.create 创建 axios,设置请求超时时间,重试请求次数,重试请求间隔
2. 设置响应拦截器
a。若返回响应内容,则直接返回错误信息,不再发送请求
b。若没有响应内容,则记录发送请求次数,若小于重试请求次数,返回 一个 promise,在发送下一次请求之前停留一段时间,再次重复请求,否则,返回错误信息
import axios from 'axios'; //创建一个axios实例 const requests = axios.create({ timeout: 5 * 1000, //请求超时时间(5秒后还未接收到数据,就需要再次发送请求) retry: 3, //设置全局重试请求次数(最多重试几次请求) retryDelay: 1000, //设置全局请求间隔 }); //响应拦截器 requests.interceptors.response.use((res) => { return Promise.resolve(res.data); }, (error) => { //console.log(error); //超时处理 error.config是一个对象,包含上方create中设置的三个参数 var config = error.config; if (!config || !config.retry) return Promise.reject(error); //如果有响应内容,就直接返回错误信息,不再发送请求 if(error.response.data){ return Promise.reject({type: "error", msg: error.response.data}); } // __retryCount用来记录当前是第几次发送请求 config.__retryCount = config.__retryCount || 0; // 如果当前发送的请求大于等于设置好的请求次数时,不再发送请求,返回最终的错误信息 if (config.__retryCount >= config.retry) { if (error.message === "Network Error") { //message为"Network Error"代表断网了 return Promise.reject({type: "warning",msg: "网络连接已断开,请检查网络"}); } else if (error.message === "timeout of 5000ms exceeded") { //网太慢了,5秒内没有接收到数据,这里的5000ms对应上方timeout设置的值 return Promise.reject({type: "warning",msg: "请求超时,请检查网络"}); } else { //除以上两种以外的所有错误,包括接口报错 400 500 之类的 return Promise.reject({type: "error",msg: "出现错误,请稍后再试"}); } } // 记录请求次数+1 config.__retryCount += 1; // 设置请求间隔 在发送下一次请求之前停留一段时间,时间为上方设置好的请求间隔时间 var backoff = new Promise(function (resolve) { setTimeout(function () { resolve(); }, config.retryDelay || 1); }); // 再次发送请求 return backoff.then(function () { return requests(config); }); }) export default requests;
五、为什么支持浏览器中发送请求也支持node发送请求?
使用的是适配器模式
- 判断环境,然后根据环境使用对应的适配器
- 在 axios.defaults.adapter 中,判断在浏览器环境中使用 XMLHttpRequest 请求,在node环境中使用http请求