记录自己处理axios请求的方式

111 阅读2分钟

首先

不知不觉,已经从事开发3年多了,从一个小白,到能自己独立做些事情。先学习了前端,一开始是html/js/css然后是jquery,再而是vue全家桶、ts等;接着公司需要,自学了Java,springboot,mysql,rabbitmq等等后端技术,然后又有做小程序和APP的需求,继而学习了uniapp。不得不说,初创小公司非常锻炼人,你得什么都要会一些才好,但风险也很大,没那么稳定。现在也考虑不了那么多,只能多做点事,希望自己能再提升一些。

这里记录自己遇到问题,总结经验,希望自己能走的更远。

问题

过去写请求相关代码的时候,总是很难受。因为我总是需要预先在data中定义一个变量,接着在methods中定义一个方法,然后在方法中写一个请求,最后来处理请求的返回值并控制加载的状态。

例如这样一个普通的定义请求的js文件

import { request } from '你封装的axios'
// 比如: user.js 文件
export const create = (data) => request({ method: 'POST', url: '/xxx/xxx', data })

以前可能是这样处理的

import { create } from 'xxx/user'

export default {
    data() {
        return {
            value: {}
            loading: false
        }
    },
    methods: {
        // 这样
        fetchCreate1() {
            this.loading = true
            return create(param)
                .then((res)=>{
                    // 处理返回值
                })
                .catch((err)=>{
                    // 处理异常
                })
                .finally(()=>{
                    this.loading = false
                })
        },
        // 或者这样
        async fetchCreate2() {
            try {
                this.loading = true
                const res = await create(param)
                // 处理返回值
            } catch(err) {
                // 处理异常
            } finally {
                this.loading = false
            }
        },
        // 还写过这种
        async fetchCreate3() {
            this.loading = true
            const [ err, res ] = await create(param)
            if(err) {
                // 处理异常
            }
            // 处理返回值
            this.loading = false
        }
    },
    mounted() {
       // 调用函数
       this.fetchCreate3()
    }
}

解决方案

想着如果每一个函数都得自己处理异常,并且处理接口返回值,感觉太麻烦了,如果能做到声明请求,就能一次性做完,岂不美哉。所以现在写一个hook来处理一下请求

import { computed, ref } from 'vue'
import { message } from 'ant-design-vue'
import { nanoid } from 'nanoid'

export const useDynamicFetch = (fn, silent = false) => {
    const data = ref()
    const id  = nanoid()
    const loading = ref(false)
    const flag = ref(false)
    
    const run = async (...args) => {
        loading.value = true
        flag.value = false
        try {
            const response = await fn(...args)
            data.value = response
            flag.value = true
        } catch(ex) {
            const msg = ex.message ?? 'other error'
            if(!silent) {
                message.error({content: msg, key: id})
            }
            flag.value = false
        } finally {
            loading.value = false
        }
        return flag.value
    }
    
    return {
        data,
        run,
        loading: computed(() => loading.value)
        flag: computed(() => flag.value),
        id
    }
}

结果

现在变成了这样,感觉好多,终于看不到回调,也看不到try/catch了, nice!

import { create } from 'xxx/user'
import { useDynamicFetch } from '@/hooks/xxxxx'

export default defineComponent({
    setup() {
        const data = ref();
        const param = {}
        const { data, run, loading, id } = useDynamicFetch(create)
        const initComponents = async () => {
             if(await run(param)) {
                 // todo
                 message.success({ content: 'success', key: id })
             }
        }
        
        onMounted(() => initComponents())
        
        return {
            data,
            loading // 可以直接给一些需要加载状态的组件使用
        }
    }
})

大功告成!

其他

不过vue2.7以前的版本,应该是用不了。如果有勇气有时间,也可以把项目vue版本升级到2.7+,这样就可以在vue2中使用vue3的部分能力,官方也提供了一个比较好的流程, 文档地址

(如果没有历史负担,个人还是很推荐使用 vue3 + ts + vite 来开发,实在太香了)