Axios学习(5)---axios请求的封装与使用

Axios学习(5)—axios请求的封装与使用

思路分析

axios 请求的封装,无非是为了方便代码管理,咱们能够使用抽离拆分的思想,将不一样功能模块的接口处理成不一样的模块,而后封装一个方法,专门用于数据交互。vue

第一步:新建 src/service/contactApi.js 文件

const CONTACT_API = {
    // 获取联系人列表
    getContactList:{
        method:'get',
        url:'/contactList'
    },
    // 新建联系人 form-data
    newContactForm:{
        method:'post',
        url:'/contact/new/form'
    },
    // 新建联系人 application/json
    newContactJson:{
        method:'post',
        url:'/contact/new/json'
    },
    // 编辑联系人
    editContact:{
        method:'put',
        url:'/contact/edit'
    },
    // 删除联系人
    delContact:{
        method:'delete',
        url:'/contact'
    }
}
export default CONTACT_API

备注:该文件的用途只有一个,定义不一样的接口请求信息(包含 method、***url***等)并导出使用。当接口增长或者删除的时候,只须要定义在该文件中便可。ios


第二步:新建 src/service/http.js 文件

import axios from 'axios'
import service from './contactApi'
import { Toast } from 'vant'
// service 循环遍历输出不一样的请求方法
let instance = axios.create({
    baseURL: 'http://localhost:9000/api',
    timeout: 1000
})
const Http = {}; // 包裹请求方法的容器

// 请求格式/参数的统一
for (let key in service) {
    let api = service[key]; // url method
    // async 做用:避免进入回调地狱
    Http[key] = async function(
        params, // 请求参数 get:url,put,post,patch(data),delete:url
        isFormData = false, // 标识是不是form-data请求
        config = {} // 配置参数
    ) {
        let newParams = {}

        // content-type是不是form-data的判断
        if (params && isFormData) {
            newParams = new FormData()
            for (let i in params) {
                newParams.append(i, params[i])
            }
        } else {
            newParams = params
        }
        // 不一样请求的判断
        let response = {}; // 请求的返回值
        if (api.method === 'put' || api.method === 'post' || api.method === 'patch') {
            try {
                response = await instance[api.method](api.url, newParams, config)
            } catch (err) {
                response = err
            }
        } else if (api.method === 'delete' || api.method === 'get') {
            config.params = newParams
            try {
                response = await instance[api.method](api.url, config)
            } catch (err) {
                response = err
            }
        }
        return response; // 返回响应值
    }
}

// 拦截器的添加
// 请求拦截器
instance.interceptors.request.use(config => {
        // 发起请求前作些什么
        Toast.loading({
            mask: false,
            duration: 0, // 一直存在
            forbidClick: true, // 禁止点击
            message: '加载中...'
        })
        return config
    }, () => {
        // 请求错误
        Toast.clear()
        Toast('请求错误,请求稍后重试')
    })
    // 响应拦截器
instance.interceptors.response.use(res => {
    // 请求成功
    Toast.clear()
    return res.data
}, () => {
    Toast.clear()
    Toast('请求错误,请求稍后重试')
})

export default Http

具体的思路步骤以下:web

  1. 首先,咱们引入contactApi.js文件,别名定义为 servicejson

    import service from './contactApi'
  2. 定义新的 axios 实例,针对当前功能模块联系人列表管理 contactList ,配置baseURL基础域名、timeout请求超时时间等等,区别于其余功能模块。axios

    let instance = axios.create({
        baseURL: 'http://localhost:9000/api',
        timeout: 1000
    })
  3. 定义 http 做为请求方法的容器,配置对应的参数(即请求方法中的其余信息,好比 headerscontent-typetoken等等)。须要注意的是,在其中咱们要区分 content-type的形式有两种:form-dataapplication/json,它们的参数配置不一样,form-data 形式的参数,咱们须要定义 Formdata 对象。具体以下:api

    let newParams = {}
    // content-type是不是form-data的判断
    if (params && isFormData) {
        newParams = new FormData()
        for (let i in params) {
            newParams.append(i, params[i])
        }
    } else {
        newParams = params
    }

    舒适提示:其中 isFormData 定义为 Boolean 变量,用于标识是否为 FormData 形式。网络

  4. 根据不一样的请求方式,发起网络请求,并导出返回值。app

    // 不一样请求的判断
    let response = {}; // 请求的返回值
    if (api.method === 'put' || api.method === 'post' || api.method === 'patch') {
        try {
            response = await instance[api.method](api.url, newParams, config)
        } catch (err) {
            response = err
        }
    } else if (api.method === 'delete' || api.method === 'get') {
        config.params = newParams
        try {
            response = await instance[api.method](api.url, config)
        } catch (err) {
            response = err
        }
    }
    return response; // 返回响应值

    注意:对于不一样方法的区别在于:getdelete 的参数在 config 中配置,而不是使用 paramsxss

  5. 设置请求拦截器与响应拦截器async

    // 拦截器的添加
    // 请求拦截器
    instance.interceptors.request.use(config => {
            // 发起请求前作些什么
            Toast.loading({
                mask: false,
                duration: 0, // 一直存在
                forbidClick: true, // 禁止点击
                message: '加载中...'
            })
            return config
        }, () => {
            // 请求错误
            Toast.clear()
            Toast('请求错误,请求稍后重试')
        })
        // 响应拦截器
    instance.interceptors.response.use(res => {
        // 请求成功
        Toast.clear()
        return res.data
    }, () => {
        Toast.clear()
        Toast('请求错误,请求稍后重试')
    })
  6. 导出src/service/http.js文件,用于其余地方的引入。

    export default Http

第三步:在入口文件中导入 http.js ,并挂载到 vue 原型上。

import Http from './service/http'
// 把Http挂载到Vue实例上
Vue.prototype.$Http = Http

第四步:在组件中使用封装的请求

// 获取联系人列表
async getList(){
    let res = await this.$Http.getContactList()
    this.list = res.data
},

注意:在使用的时候,咱们须要结合 asyncawait 才能正确使用。具体的使用方法是:

  1. 在定义的网络请求函数前增长 async 标识。
  2. 在接收请求返回数据的时候,增长 await 标识。
  3. 提示:在上面函数中,只有在 res 拿到后才会执行 this.list = res.data; 至关于在对应的 then 中执行的语句,避免了回调地狱。

总结

在进行项目开发的时候,咱们须要对网络请求的方法进行封装,能够有效地减小后期代码维护的难度,建议开发者根据不一样的功能模块进行拆分,方便后期代码问题的定位。另外,也能实现代码的低耦合,避免出现更多的重复代码。


舒适提示

更多博文,请关注:xssy5431 小拾岁月
扫码: