Axios

axios 是什么

    1. Axios 是一个基于 promiseHTTP 库,可以用在浏览器和 node.js 中。前端最流行的 ajax 请求库,
    1. react/vue 官方都推荐使用 axiosajax 请求

axios 特点

  • 基于 promise 的异步 ajax 请求库,支持promise所有的API
  • 浏览器端/node 端都可以使用,浏览器中创建XMLHttpRequests
  • 支持请求/响应拦截器
  • 支持请求取消
  • 可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据
  • 批量发送多个请求
  • 安全性更高,客户端支持防御 XSRF,就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略

全局修改axios默认配置

axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

配置优先级

request config> instance.defaults> 系统默认

// 创建一个实例,这时的超时时间为系统默认的 0
var instance = axios.create();
// 通过instance.defaults重新设置超时时间为2.5s,因为优先级比系统默认高
instance.defaults.timeout = 2500;
// 通过request config重新设置超时时间为5s,因为优先级比instance.defaults和系统默认都高
instance.get('/longRequest', {
  timeout: 5000
});

axios 常用语法

  • axios(config): 通用/最本质的发任意类型请求的方式
  • axios(url[, config]): 可以只指定 url 发 get 请求
  • axios.request(config): 等同于 axios(config)
  • axios.get(url[, config]): 发 get 请求
    • 直接在url中拼接数据
    axios({
        url: "http://123.207.32.32:8000/home/multidata?aaa=1&type=2"
    }).then(res => console.log(res))
    
    • config中配置params属性
    axios({
    url: "http://123.207.32.32:8000/home/multidata",
        params: {
            aaa: 1,
            type: 2
        }
    }).then(res => console.log(res)).catch(err => console.log(err))
    
  • axios.delete(url[, config]): 发 delete 请求
  • axios.post(url[, data, config]): 发 post 请求
axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
}).then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});
  • axios.put(url[, data, config]): 发 put 请求
  • axios.defaults.xxx: 请求的默认全局配置
  • axios.interceptors.request.use(): 添加请求拦截器
  • axios.interceptors.response.use(): 添加响应拦截器
  • axios.create([config]): 创建一个新的 axios(它没有下面的功能)
  • axios.Cancel(): 用于创建取消请求的错误对象
  • axios.CancelToken(): 用于创建取消请求的 token 对象
  • axios.isCancel(): 是否是一个取消请求的错误
  • axios.all(promises): 用于批量执行多个异步请求









 

axios.all([]);//传入一个数组,数组元素都是一个axios网络请求
axios.all([
  axios({
    url:"http://123.207.32.32:8000/home/data"
  }),
  axios({
    url:"http://123.207.32.32:8000/home/multidata"
  })
]).then(res=>console.log(res))
res是一个数组,两个请求结果返回的数据组成的数组
  • axios.spread(): 用来指定接收所有成功数据的回调函数的方法

拦截器

// 添加一个请求拦截器
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });

// 添加一个响应拦截器
axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });

取消请求

  • 可以使用 CancelToken.source 工厂方法创建 cancel token,像这样:
var CancelToken = axios.CancelToken;
var source = CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});

// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');
  • 还可以通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token
var CancelToken = axios.CancelToken;
var cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  })
});

// 取消请求
cancel();

封装

  • 给不同环境配置不同请求地址 根据 process.env.NODE_ENV 配置不同的 baseURL,使项目只需执行相应打包命令,就可以在不同环境中自动切换请求主机地址

const getBaseUrl = (env) => {
    let base = {
        production: '/',
        development: 'http://localhost:3000',
        test: 'http://localhost:3001',
    }[env];
    if (!base) {
        base = '/';
    }
    return base;
};

class NewAxios {
    constructor() {
        this.baseURL = getBaseUrl(process.env.NODE_ENV);
    }
}
  • timeout:超时时间
  • widthCredentials:允许携带凭证

完整封装后的代码

import axios from 'axios';

const getBaseUrl = (env) => {
    let base = {
        production: '/',
        development: 'http://localhost:3000',
        test: 'http://localhost:3001',
    }[env];
    if (!base) {
        base = '/';
    }
    return base;
};

class NewAxios {
    constructor() {
        this.baseURL = getBaseUrl(process.env.NODE_ENV);
        this.timeout = 10000;
        this.withCredentials = true;
    }

    setInterceptors = (instance, url) => {
        instance.interceptors.request.use((config) => {
            // 在这里添加loading
            // 配置token
            config.headers.AuthorizationToken = localStorage.getItem('AuthorizationToken') || '';
            return config;
        }, err => Promise.reject(err));

        instance.interceptors.response.use((response) => {
            // 在这里移除loading
            // todo: 想根据业务需要,对响应结果预先处理的,都放在这里
            return response;
        }, (err) => {
            if (err.response) { // 响应错误码处理
                switch (err.response.status) {
                    case '403':
                        // todo: handler server forbidden error
                        break;
                    // todo: handler other status code
                    default:
                        break;
                }
                return Promise.reject(err.response);
            }
            if (!window.navigator.online) { // 断网处理
                // todo: jump to offline page
                return -1;
            }
            return Promise.reject(err);
        });
    }

    request(options) {
        // 每次请求都会创建新的axios实例。
        const instance = axios.create();
        const config = { // 将用户传过来的参数与公共配置合并。
            ...options,
            baseURL: this.baseURL,
            timeout: this.timeout,
            withCredentials: this.withCredentials,
        };
        // 配置拦截器,支持根据不同url配置不同的拦截器。
        this.setInterceptors(instance, options.url);
        return instance(config); // 返回axios实例的执行结果
    }
}

export default new NewAxios();

//import axios from 文件名
axios.request({url: '/data'})