axios统一封装get,post 请求,统一api思路,统一处理token过期

版权声明:总结不易,转载请说明出处哦! https://blog.csdn.net/qq_36407748/article/details/86658638

先看效果(请求前加载loading,请求完毕后关闭loading
在这里插入图片描述

配置的请求头token

在这里插入图片描述

axios 的统一封装api

# 本实例是以react项目演示

# src项目目录
	|-- api  		
		|-- index.js 			统一封装接口api
	|-- assets 	
		|-- loading.css			c3完成的loading的样式
    |-- utils		
		|-- http.js				axios 封装
    |-- App.js					组件		

http.js(此封装会在每个接口请求前都会加载一次loading)


import axios from 'axios';

// 创建实例时设置配置的默认值

/**
 * 自定义实例默认值
 */
var instance = axios.create({
  // baseURL: 'http://yapi.demo.qunar.com/mock/1152', // 公	共接口url(如果有多个的公共接口的话,需要处理)
  timeout: 3000, // 请求超时
});
// /api/getUserById


// 请求拦截器, 进行一个全局loading  加载,这种情况下所有的接口请求前 都会加载一个loading

/**
 * 添加请求拦截器 ,意思就是发起请求接口之前做什么事,一般都会发起加载一个loading
 * */

//  如果不想每个接口都加载loading ,就注释掉请求前拦截器,在http这个类中处理

instance.interceptors.request.use(
  config => {
    // 在发送请求之前做些什么(... 这里写你的展示loading的逻辑代码 )
    isShowLoading(true);
    // 获取token,配置请求头
    // const TOKEN = localStorage.getItem('Token')
    // 演示的token(注意配置请求头,需要后端做cros跨域处理,我这里自己前端配的跨域)
    const TOKEN = '1fd399bdd9774831baf555ae5979c66b'
    if(TOKEN){
      // 配置请求头 token
      config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
      config.headers['Authorization'] = TOKEN;
   }
    return config;
  },
  error => {
    // 对请求错误做些什么,处理这个错误

    // 可以直接处理或者展示出去,toast show()
    console.warn(error);

    return Promise.reject(error);
  }
);

/**
 * 添加响应拦截器,意思就是发起接口请求之后做什么事,此时只有两种情况,
 * 要么成功,要么失败,但是不管成功,还是失败,我们都需要关闭请求之前的
 * 发起的loading,那既然要处理loading,就把loading做成全局的了,
 * 这里自定义一个处理加载loding 和关闭loading的方法,而且这个loading
 * 要不要加载,会根据外部传入的布尔值来决定,默认是false:不展示
 * */

instance.interceptors.response.use(
  function(response) {
    // 对响应数据做点什么
    isShowLoading(false);
    console.log(response)
    // 根据你们家的后端定义请求过期后返回的参数,处理token过期问题
    // 我这个接口木有token啊,这里演示下
    // 判断
    const {status} = response.data;
    // 判断状态码401或者其它条件,不知道判断哪个的去问你家后台
    if(Object.is(status,401)){
      // token过期后处理
      // 1.删除你本地存储的那个过期的token
      
      // 2. 跳转到登陆页(因为没有装路由,不写了,重新登陆赋值)

      //  todo...
    }
    return response;
  },
  function(error) {
    // 对响应错误做点什么
    isShowLoading(false);
    return Promise.reject(error);
  }
);

// 如果与你配合的ui中,有loading组件的话,你直接用它的就可以了

// to do...
/**
 * 是否开启loading
 * @param {*} payload { type:Boolean }
 */

function isShowLoading(payload) {
// 获取dom节点
 const loading = document.getElementById('loading');
 payload ? loading.style.display = 'block' : loading.style.display = 'none';

}

/**
 * 使用es6中的类,进行简单封装
 */

class http {
  // 使用async ... await
  static async get(url, params) {
    console.log(params)
    return await instance.get(url, {params}) 
  }
  static async post(url, params) {
    console.log(params)
    return await instance.post(url, params);
  }
}


export default http;

// 处理跨域,在 package.json ,最后一行加入这个

  "proxy":"http://yapi.demo.qunar.com/mock/1152"
  

自定义一个c3的 loading

在index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!-- 自定义的loading -->
    <div id="loading">
      <div class="spinner">
        <div class="double-bounce1"></div>
        <div class="double-bounce2"></div>
      </div>
    </div>
  </body>

</html>

loading的样式. — assets/loading.css

body {
  margin: 0;
  padding: 0;
}
#loading {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  z-index: 99;
  display: none;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.2);
}
.spinner {
  width: 60px;
  height: 60px;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-left: -30px;
  margin-top: -30px;
}
 
.double-bounce1, .double-bounce2 {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background-color: #4403f7;
  opacity: 0.6;
  position: absolute;
  top: 0;
  left: 0;
   
  -webkit-animation: bounce 2.0s infinite ease-in-out;
  animation: bounce 2.0s infinite ease-in-out;
}
 
.double-bounce2 {
  -webkit-animation-delay: -1.0s;
  animation-delay: -1.0s;
}
 
@-webkit-keyframes bounce {
  0%, 100% { -webkit-transform: scale(0.0) }
  50% { -webkit-transform: scale(1.0) }
}
 
@keyframes bounce {
  0%, 100% {
    transform: scale(0.0);
    -webkit-transform: scale(0.0);
  } 50% {
    transform: scale(1.0);
    -webkit-transform: scale(1.0);
  }
}

在 api/index.js 统一封装api接口

import http from '../utils/http'

/**
 * 这里统一处理项目中所有的 api 接口
 */

// demo 某功能比如获取一个列表
export const getData = params => http.get('/api/getUserById',params);

// to do ...

在组件中调用 App.js 中

import React, { Component } from 'react'

// 引入封装的接口方法
import { getData } from './api'

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      list:[],
    }
  }
  render() {
    const {list} = this.state;
    return (
      <div>
        {
          list.map((item,index)=>{
            return(
              <p key={index}>{ item.subjectName }</p>
            )
          })
        }
      </div>
    )
  }
  componentDidMount(){
     // 调用
    getData().then(res => {
      const {totalSubjectType} = res.data.data;
      this.setState({list:totalSubjectType})
    })
  }
}
export default App;

全局加载loading样式— index.js

import React from "react";

import ReactDOM from 'react-dom';

import App from './App';

import './assets/loading.css'

ReactDOM.render(<App/>,document.getElementById('root'))

http.js (按需加载loading,由你决定接口调用前要不要加载loading)

import axios from 'axios';

// 创建实例时设置配置的默认值

/**
 * 自定义实例默认值
 */
var instance = axios.create({
  baseURL: 'http://yapi.demo.qunar.com/mock/1152', // 公共接口url(如果有多个的公共接口的话,需要处理)
  timeout: 3000, // 请求超时
});

/**
 * 添加响应拦截器,意思就是发起接口请求之后做什么事,此时只有两种情况
 */
instance.interceptors.response.use(
  function(response) {
    // 对响应数据做点什么
    isShowLoading(false);
    return response;
  },
  function(error) {
    // 对响应错误做点什么
    isShowLoading(false);
    return Promise.reject(error);
  }
);

// 如果与你配合的ui中,有loading组件的话,你直接用它的就可以了

// to do...
/**
 * 是否开启loading
 * @param {*} payload { type:Boolean }
 */

function isShowLoading(payload) {
// 获取dom节点
 const loading = document.getElementById('loading');
 payload ? loading.style.display = 'block' : loading.style.display = 'none';

}

/**
 * 使用es6中的类,进行简单封装
 */

class http {
  // 使用async ... await
  /**
   * axios get 请求封装
   * @param {*} url 接口地址
   * @param {*} params 接口参数?可选 { type:object }
   * @param {*} isShow 接口请求前是否展示loading
   */
  static async get(url, params, isShow = false) {
    isShowLoading(isShow)
    return await instance.get(url, {params}) 
  }
  /**
   * axios post 请求封装
   * @param {*} url 接口地址
   * @param {*} params 接口参数?可选 { type:object }
   * @param {*} isShow 接口请求前是否展示loading
   */
  static async post(url, params, isShow = false) {
    isShowLoading(isShow)
    return await instance.post(url, params);
  }
}

export default http;

按需加载loading 情况下 , api/index.js 统一封装api接口

import http from '../utils/http'

/**
 * 这里统一处理项目中所有的 api 接口
 */

// demo 某功能比如获取一个列表(传入你要不要展示loading的参数)
export const getData = (params,isShow) => http.get('/api/getUserById',params, true);

调用方法跟上边一样,就不写了,这个axios每个人封装的方式都不一样,看的理解一下,自己封装一个吧,有好的建议欢迎互相探讨沟通!

展开阅读全文

没有更多推荐了,返回首页