Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

200错误统一处理推荐 #21

Open
lq782655835 opened this issue Oct 11, 2018 · 0 comments
Open

200错误统一处理推荐 #21

lq782655835 opened this issue Oct 11, 2018 · 0 comments

Comments

@lq782655835
Copy link
Owner

对于接口层来说,后端经常定义的结构如下:

{
    code: [Number], // 状态码
    desc: [String], // 详细描述
    detail: [Array, Object] // 前端需要的数据
}

bad

batchAddVariable({ globalParamList: validList })
    .then(res => {
        if (res === SERVER_ERROR_CODE.SUCCESS) { // !!!Bad: how many interface, how many judge 200
            this.close(true)
            this.$toast.show(res.detail.colletion) // !!!Bad: always get detail data
        } else { // !!!Bad: too much nest,reading difficulty
            this.$toast.show(res.desc)
            if (res === SERVER_ERROR_CODE.REPEAT) {
                ...
            }
        }
    })

good

batchAddVariable({ globalParamList: validList })
    .then(data => {
        this.close(true)
        this.$toast.show(data.colletion)
    })
    .catch(res => {
        if (res === SERVER_ERROR_CODE.REPEAT) {
            ...
        }
    })

解决方案

http层axios拿到数据后进行统一处理

import Vue from 'vue'
import axios from 'axios'

const service = axios.create({
    baseURL: rootURL, // api的base_url
    timeout: 15000, // 请求超时时间
})

// request拦截器
service.interceptors.request.use(
    config => {
        if (config.method === 'post' || config.method === 'put' || config.method === 'delete') {
            config.headers['Content-Type'] = 'application/json'
            if (config.type === 'form') {
                config.headers['Content-Type'] = 'multipart/form-data'
            } else {
                // 序列化
                config.data = JSON.stringify(config.data)
            }
        }

        return config
    },
    error => {
        Promise.reject(error)
    }
)

// respone拦截器
service.interceptors.response.use(
    response => {
        const res = response.data
        if (res.code === SERVER_ERROR_CODE.SUCCESS) { // 统一处理
            return res.detail // 直接返回数据
        } else {
            Vue.prototype.$toast.show(res.desc) // 错误统一报出
            return Promise.reject(res)
        }
    },
    error => {
        return Promise.reject(error)
    }
)

export default service

到此基本就可以很优雅的写逻辑代码了。不过还有个点可以继续优化。通常情况,后台返回非200错误,只需要$toast提示结果就行,catch代码部分可以省略。类似如下:

batchAddVariable({ globalParamList: validList })
    .then(data =>  this.close(true))
    // .catch(() => {}) // 业务通常这里不需要写

多么简洁的代码,但Promise执行reject代码,浏览器会报Uncaught (in promise)错误。这是因为中断了Promise操作但又没有对其进行处理,故由此错误。只需要使用unhandledrejection全局处理即可。

// Promise Catch不报错
window.addEventListener('unhandledrejection', event => event.preventDefault())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant