标签搜索
隐藏侧边栏

【Vue3+Express实战-6】二次封装Axios

搞前端的半夏
2022-04-24 / 0 评论 / 1 点赞 / 435 阅读 / 4,040 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-04-27,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

大家好,我是半夏👴,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注➕ 点赞 👍 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师~关注公众号:搞前端的半夏,了解更多前端知识! 点我探索新世界!

在上一节课程中,我们成功的搭建了新增课程的页面,并成功使用Axios发送POST请求,但是呢,使用Axios的方式是有些许的问题的。通常在一个企业级或者个人开源的项目中,Axios会被二次封装。

二次封装的好处有哪些呢?

  1. 统一 url 配置
  2. 统一 api 请求
  3. request (请求)拦截器,例如:带上token等,设置请求头
  4. response (响应)拦截器,例如:统一错误处理,页面重定向等
  5. 统一处理http错误码和自定义的code

话不多说,我们直接开始吧!

创建src\utils\axiosUtil.js

这个文件就是用来封装Axios,我们想要在其他文件中使用Axios,这里我们就需要创建并抛出一个Axios实例。

import axios from "axios"

let axiosInstance = axios.create({
})

export default axiosInstance;

接下来,我们就开始进行配置。打开http://axios-js.com/zh-cn/docs/index.html#请求配置查看Axios提供的配置项。

基本配置

统一url配置

首先,我们需要配置的是统一的请求接口。我们在src\views\AddTutorial.vue直接使用axios发post请求http://localhost:3000/api/tutorials,这里的http://localhost:3000/api就是一个统一的Url。

image-20220424110340130

let axiosInstance = axios.create({
    baseURL:'http://localhost:3000/api',
})

有了这个baseURL在发送post请求的时候,就不需要加上http://localhost:3000/api,Axios会自动给我们加上!!!

环境变量

但是http://localhost:3000/api这个只是本地测试的接口,我们还有服务器测试接口,上线后的接口。针对不同接口,我们每次都需要修改,是一件很麻烦的事情,还好我们使用的是node(npm)作为的辅助开发工具。他天生自带一个process全局变量。并且Vue/CLI创建的项目,支持设置模式和环境变量。

模式是 Vue CLI 项目中一个重要的概念。默认情况下,一个 Vue CLI 项目有三个模式:

  • development 模式用于 vue-cli-service serve
  • test 模式用于 vue-cli-service test:unit
  • production 模式用于 vue-cli-service buildvue-cli-service test:e2e

更多内容我们可以直接去 https://cli.vuejs.org/zh/guide/mode-and-env.html查看更多信息。

我们在项目根目录下创建两个文件,并加上环境变量键值对。

  • .env.development

    VUE_APP_APIURL=http://localhost:3000/api

  • .env.production

    VUE_APP_APIURL=发布环境接口

.env.development存放开发环境api url。,.env.production存放发布环境api url。

有了这个怎么使用呢?

指定mode

在package.json.scripts中,我们目前有两个脚本,一个是用来启动本地服务,一个用来打包。

其实这两个脚本后面都有一个默认的mode.

"serve": "vue-cli-service serve",
"build": "vue-cli-service build"

完整的代码应该是;

"serve": "vue-cli-service serve --mode developemnt",
"build": "vue-cli-service build --mode production"

--mode developemnt 会使用.env.development的值

--mode developemnt 会使用.env.production的值

使用process.env

我们刚才说了,全局有一个process,它上面挂载了env。通过env找到我们的VUE_APP_APIURL

我们修改axiosUtils

let axiosInstance = axios.create({
   baseURL:process.env.VUE_APP_APIURL,
})

当我们执行yarn serve yarn build,就会切换到对应的值。

请求头

我们后端支持支持什么格式的数据,这里就可以指定具体的Content-type。我们这个项目就指定json即可

import axios from "axios"
let axiosInstance = axios.create({
    baseURL:process.env.VUE_APP_APIURL,
    headers:{
        "Content-type":"application/json"
    }
})

超时时间

一个请求超过一段时间自动停止。

 // 设置超时时间
    timeout: 10000,

request 拦截器

在请求发出之前,抽离出共同的方法。

例如 对于所有的psot请求,我们可能需要去进行序列化参数(后端要求序列化的参数),

又例如,我们发送的请求是错误的,我们要如何处理。

又又例如:我们的请求接口是需要token的,但是登录的接口不需要,此时我们在请求时就需要拦截,给除了登录接口之外的其他接口加上token。

参考官网的写法http://axios-js.com/zh-cn/docs/index.html#%E6%8B%A6%E6%88%AA%E5%99%A8

axiosInstance.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    console.log("我是请求拦截器")
    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});

response 拦截器

在接收到请求之后,抽离出共同的方法。

例如: 接口400怎么办,接口500怎么办!

又例如 :接收到的数据怎么办!

axiosInstance.interceptors.response.use(function (response) {
    let data;
    // IE9时response.data是undefined,因此需要使用response.request.responseText(Stringify后的字符串)
    if (response.data == undefined) {
        data = response.request.responseText
    } else {
        data = response.data
    }
  
    // 对响应数据做点什么
    return data;
}, function (err) {
    console.log("接收到结果")

    if (err && err.response) {
        console.log(err.response.status)
        switch (err.response.status) {
            case 400:
            err.message = '请求错误'
            break
    
            case 401:
            err.message = '未授权,请登录'
            break
    
            case 403:
            err.message = '拒绝访问'
            break
    
            case 404:
            err.message = `请求地址出错: ${err.response.config.url}`
            break
    
            case 408:
            err.message = '请求超时'
            break
    
            case 500:
            err.message = '服务器内部错误'
            break
    
            case 501:
            err.message = '服务未实现'
            break
    
            case 502:
            err.message = '网关错误'
            break
    
            case 503:
            err.message = '服务不可用'
            break
    
            case 504:
            err.message = '网关超时'
            break
    
            case 505:
            err.message = 'HTTP版本不受支持'
            break
    
            default:
        }
    }

    // 对响应错误做点什么
    return Promise.reject(err);
});

统一Api管理

对于同一个模块的请求我们通常是放在封装在一个文件夹里。例如这里的课程管理,我会新建src\api\TutorialDataApi.js文件。

在这个文件里,编写涉及到可册灰姑娘的增删改查接口。

例如我们上节课程的新增接口。

import axiosUtil from '../utils/axiosUtil.js'

class TutorialDataApi{
    create(data){
        console.log(data)
        return axiosUtil.post('/tutorials',data)
    }
    delete(data){
    。。。。。。。
	}
    
}
export default new TutorialDataApi();

使用

src\views\AddTutorial.vue我们重写Submit方法。

 TutorialDataApi.create(tutorial).then((res)=>{
      console.log(res)
  },err=>{
    console.log(err)
  })
0

评论区