axios-api设计

axios-api设计

      • 区分环境
      • 超时时间
      • 跨域携带cookie
      • post请求处理数据格式(可选)
      • 请求拦截
      • 响应拦截
      • 完整配置
      • 分离与合并
      • 使用示例
      • 参考与推荐

区分环境

import axios from 'axios';

const env = process.env.NODE_ENV;
const PRO_URL = "xxxx";
const DEV_URL = "xxxx";
const TEST_URL = "xxxx";

switch (env) {

    case "production": {
        axios.defaults.baseURL = PRO_URL;
        break;
    }
    case "development": {
        axios.defaults.baseURL = DEV_URL;
        break;
    }
    case "test": {
        axios.defaults.baseURL = TEST_URL;
        break;
    }
    default: axios.defaults.baseURL = DEV_URL;
}

package.json中配置启动脚本

  "scripts": {
    "server:dev": "SET NODE_ENV=development && node app.js",
    "server:test": "SET NODE_ENV=test && node app.js",
    "server:pro": "SET NODE_ENV=production && node app.js"
  },


超时时间

//设置超时时间 10s
axios.defaults.timeout=10000;

跨域携带cookie

//设置是否允许跨域携带cookie
axios.defaults.withCredentials = true;

post请求处理数据格式(可选)

import qs from 'qs'
//post主体数据形如:key1=value1&key2=value2  x-www-form-urlencoded
axios.defaults.headers['Content-Type']='application/x-www-form-urlencoded';
axios.defaults.transformRequest=data=>qs.stringify(data)

请求拦截

axios.interceptors.request.use(
    config => {
        //请求携带token
        let token=localStorage.getItem('token');
        token&&(config.headers.Authorization=token);
        return config
       
    },
    error=>Promise.reject(error)
)

响应拦截

//直接返回响应主体
axios.interceptors.response.use(
    response => response.data,
    error=>{
        const {response} =error;   
        if(response){
            //有响应内容 根据不同状态码进行不同处理
            switch(response.status){
                case 401:{ 
                    //=>权限处理,一般是未登录 ,可跳转至登录页或提示未登录
                    break;
                }
                case 403:{ 
                    //=>服务器拒绝执行,一般是token过期
                    break;
                }
                case 404:{ 
                    //=>资源找不到,可跳转至404页面
                    break;
                }           
            }

        }else{
            //无响应内容 断网或服务器错误
            if(!window.navigator.onLine){
                return Promise.reject("网络连接中断,请检查...")
            }
            //服务器错误,直接返回错误信息
            return Promise.reject(error)
        }
    }
)

完整配置

import axios from 'axios';
import qs from 'qs';
axios.defaults.headers['Content-Type']='application/x-www-form-urlencoded';
axios.defaults.transformRequest=data=>qs.stringify(data)
axios.defaults.timeout=10000;
axios.defaults.withCredentials = true;
const env = process.env.NODE_ENV;
const PRO_URL = "xxxx";
const DEV_URL = "xxxx";
const TEST_URL = "xxxx";

switch (env) {
    case "production": {
        axios.defaults.baseURL = PRO_URL;
        break;
    }
    case "development": {
        axios.defaults.baseURL = DEV_URL;
        break;
    }
    case "test": {
        axios.defaults.baseURL = TEST_URL;
        break;
    }
    default: axios.defaults.baseURL = DEV_URL;
}

axios.interceptors.request.use(
    config => {
        let token=localStorage.getItem('token');
        token&&(config.headers.Authorization=token);
        return config
    },
    error=>Promise.reject(error)
)

axios.interceptors.response.use(
    response => response.data,
    error=>{
        const {response} =error;
        if(response){
            switch(response.status){
                case 401:{ 
                    //do something
                    break;
                }
                case 403:{ 
                     //do something
                    break;
                }
                case 404:{ 
                     //do something
                    break;
                }
            }

        }else{
            if(!window.navigator.onLine){
                return Promise.reject("网络连接中断,请检查...")
            }
            return Promise.reject(error)
        }
    }
)

export default axios

分离与合并

将每一个功能模块请求单独抽离,最后使用统一出口导出,这样使得api调用层次更为清晰

/src/api
/src/api/index 接口统一出口
/src/api/http 放置重新设计的axios
/src/api/service1
/src/api/service2
...

api/service1

import axios from './http';
export default (params, succCb, errCb = (err) => console.error(err)) => {
    axios.get('url', { params }).then(succCb).catch(errCb)
}

api/service2

import axios from './http';
export default (params, succCb, errCb = (err) => console.error(err)) => {
    axios.post('url', params).then(succCb).catch(errCb)
}

api/index

import service1 from './service1';
import service2 from './service2';
export  {
    service1,
    service2
}

使用示例

  1. 前端采用create-react-app生成项目
  2. src下新建api文件夹
  3. api文件夹下新建http.js文件并写入如下代码
//这里采用了简化配置
import axios from 'axios';
import qs from 'qs';
axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.transformRequest = data => qs.stringify(data)
axios.defaults.timeout = 10000;
axios.defaults.withCredentials = true;
axios.interceptors.response.use(
    response => response.data,
    error => Promise.reject(error)
)
export default axios
  1. api文件夹下新建getManifest.js文件并写入如下代码
import axios from './http';
export default (params, succCb, errCb = (err) => console.error(err)) => {
    axios.get('/manifest.json', { params }).then(succCb).catch(errCb)
}
  1. api文件夹下新建sendPostMsg.js文件并写入如下代码
import axios from './http';
export default (params, succCb, errCb = (err) => console.error(err)) => {
    axios.post('http://127.0.0.1:4000/msg', params).then(succCb).catch(errCb)
}
  1. api文件夹下新建index.js文件并写入如下代码
import getManifest from './getManifest.js';
import sendPostMsg from './sendPostMsg';
export { getManifest,sendPostMsg }
  1. src/index 写入如下内容
import React, { useEffect, useState } from 'react';
import { render } from 'react-dom'
import { getManifest, sendPostMsg } from './api'

function App() {
  const [data, setData] = useState('')
  useEffect(() => {
    const successCallback = res => setData(res.name)
    const errorCallback = err => console.error(err);
    //get请求
    getManifest({}, successCallback, errorCallback);
    //post请求
    sendPostMsg({ msg: '冷月心' }, (res) => {
      const h2 = document.createElement('h2');
      h2.innerHTML = res.msg;
      document.body.appendChild(h2)
    })

  }, [])
  return <h1>{data}</h1>
}

render(<App />, document.getElementById("root"))
  1. node配置app.js
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
//配置bodyParser 处理post请求
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
//允许跨域
const corsMiddleware = function (req, res, next) {
    res.header('Access-Control-Allow-Origin', req.headers.origin);
    res.header('Access-Control-Allow-Credentials', true);
    next();
};
app.use(corsMiddleware);
//处理表单的post请求,req.body用来接收数据
app.post('/msg', function (req, res) {
    res.send(req.body);
})
//设置监听
app.listen(4000, function () {
    console.log('run server___');
})

  1. 效果图

axios-api设计_第1张图片

参考与推荐

Axios的二次封装和API接口管理规范

你可能感兴趣的:(react)