Articles sur la fonction React - encapsulation de la bibliothèque de requêtes réseau axios

Les besoins de chaque projet ont des écarts, alors assurez-vous d'ajuster la configuration appropriée en fonction de vos propres projets.
Si vous avez de bonnes suggestions, veuillez répondre dans la zone de commentaires !

1. Créez le fichier httpload.js

import axios from 'axios';
import {
    
     message } from 'antd';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

const http = axios.create({
    
    
  baseURL: process.env.REACT_APP_BASE_API, // 从.env变量中读取的后台url地址
  timeout: 300000, // 超时时长5分钟,
  crossDomain: true
});

http.defaults.headers.post['Content-Type'] = 'multipart/form-data;application/json;charset=UTF-8;';

// 当前正在请求的数量
let needLoadingRequestCount = 0;

// 显示loading
function showLoading(target) {
    
    
  if (needLoadingRequestCount === 0) {
    
    
    NProgress.start();
  }
  needLoadingRequestCount++;
}

// 隐藏loading
function hideLoading() {
    
    
  needLoadingRequestCount--;
  needLoadingRequestCount = Math.max(needLoadingRequestCount, 0); // 做个保护
  if (needLoadingRequestCount === 0) {
    
    
    NProgress.done();
  }
}

// 添加请求拦截器
let tempConfig = '';
http.interceptors.request.use(
  config => {
    
    
    // 判断当前请求是否设置了不显示Loading
    tempConfig = config;
    tempConfig.url = decodeURI(encodeURI(tempConfig.url).replace('%E2%80%8B', ''));
    if (config.headers.showLoading !== false) {
    
    
      showLoading(config.headers.loadingTarget);
    }
    const {
    
     token } = sessionStorage;
    if (token) {
    
    
      config.headers.common.Authorization = `Bearer ${
      
      token}`;
    }
    return config;
  },
  err => {
    
    
    // 判断当前请求是否设置了不显示Loading
    if (tempConfig.headers.showLoading !== false) {
    
    
      hideLoading();
    }
    message.error('请求超时!');
    return Promise.resolve(err);
  }
);

// 响应拦截器
http.interceptors.response.use(
  response => {
    
    
    // 判断当前请求是否设置了不显示Loading(不显示自然无需隐藏)
    if (response.config.headers.showLoading !== false) {
    
    
      hideLoading();
    }
    return response;
  },
  error => {
    
    
    hideLoading();
    if (error.response && error.response.status) {
    
    
      switch (error.response.status) {
    
    
        case 401:
          // 如有刷新token的需求,可放开以下代码
          // var config=error.config;
          // refreshTokenFuc(isRefreshToken, config, retryRequests);
          message.error('登录信息已过期,请重新登录!');
          break;
        default:
          break;
      }
      return Promise.reject(error.response);
    }
    return Promise.reject(error.response);
  }
);

export default http;

2. Créez un dossier api et placez le code suivant dans index.js

Une fois l'API encapsulée, elle est exportée pour être utilisée sur la page

import request from "@/http/httpload.js"
	export default{
    
    
		getData(data){
    
    
		return request({
    
    
			url:"/api/xxx",
			method:"post",
			data:data
		})
    },
    getIpAddress(data){
    
    
		return request({
    
    
			url:"/api/xxx",
			method:"get",
			parmas:data
		})
	}
}

3. Appelé dans la page de réaction

import React, {
    
     Component } from 'react';
import {
    
     Button, message } from 'antd';
import IPApi from '@/api/index';
class Http extends Component {
    
    
  constructor(props) {
    
    
    super(props);
    this.state = {
    
    
      ipAddress: {
    
    }
    };
  }
  async getIp() {
    
    
    let res = await IPApi.getIpAddress('xxxx.xx.xx');
    message.success('查询IP成功');
    this.setState({
    
    
      ipAddress: res.data.data
    });
  }
  render() {
    
    
    return (
      <div>
        <div>{
    
    JSON.stringify(this.state.ipAddress)}</div>
        <Button onClick={
    
    () => this.getIp()}>网络请求</Button>
      </div>
    );
  }
}

export default Http;

4. Actualiser le code refreshToken [pas nécessaire, à utiliser selon les besoins spécifiques]

S'il est nécessaire d'actualiser le jeton, placez le code suivant dans le fichier httpload.js.
Remarque : le code suivant doit être placé avant de répondre à la demande d'interception

Problème à résoudre : Après rafraîchissement du refreshToken, le nouveau Token est obtenu normalement, et la précédente mauvaise requête est automatiquement redemandée. Le retour de données est normal, mais la page ne sera pas re-rendue, car la requête de données a été interceptée Jusqu'à présent, il n'y a rien de bon La solution nécessite que l'utilisateur clique sur n'importe quel bouton de la page ou actualise la page

let isRefreshToken = false;//是否正在刷新token
let retryRequests = []; //用于存储错误请求的数组
// 刷新token方法
function refreshTokenFuc(isRefreshToken, config, retryRequests) {
    
    
  if (!isRefreshToken) {
    
    
    isRefreshToken = true;
    var data = {
    
     refreshtoken: sessionStorage.refreshtoken }
    //TokenApi是自己封装的axios网络请求, 这里替换成你们自己请求后端刷新token的请求即可
    TokenApi.refreshToken(data).then(res => {
    
    
      sessionStorage.token = res.data.data.token.access_token;
      sessionStorage.refreshtoken = res.data.data.token.refresh_token;
      config.headers["Authorization"] = 'Bearer ' + res.data.data.token.access_token;
      retryRequests.forEach((cb) => cb(res.data.data.token.access_token));
      retryRequests = [];
      return http.request(config);
    }).catch(error => {
    
    
      message.error("身份验证失败,请重新登录!");
      sessionStorage.clear();
      setTimeout(() => {
    
    
        router.replace({
    
    
          path: '/login',
          // query: { redirect: router.currentRoute.fullPath }
        })
      }, 1500)
    }).finally(() => {
    
    
      isRefreshToken = false;
    })
  } else {
    
    
   //存储错误的请求,待刷新token完成后,重新发起请求
    return new Promise((resolve) => {
    
    
      retryRequests.push((token) => {
    
    
        config.headers["Authorization"] = 'Bearer ' + token;
        resolve(http.request(config))
      })
    })
  }
}

Guess you like

Origin blog.csdn.net/r657225738/article/details/118599315