【发布时间】:2018-07-17 08:11:12
【问题描述】:
我正在使用 Vuex + axios,我想知道处理 vuex + axios 错误的最佳实践。我现在正在做的是,当我使用 axios 请求并返回错误时,它将以突变形式提交并更新我的状态。我想要做的是,如果我的请求有响应错误,它将返回到我的组件,以便我可以更快地处理错误。
和 Angular 一样,有一个依赖注入,响应会返回到组件。
【问题讨论】:
我正在使用 Vuex + axios,我想知道处理 vuex + axios 错误的最佳实践。我现在正在做的是,当我使用 axios 请求并返回错误时,它将以突变形式提交并更新我的状态。我想要做的是,如果我的请求有响应错误,它将返回到我的组件,以便我可以更快地处理错误。
和 Angular 一样,有一个依赖注入,响应会返回到组件。
【问题讨论】:
让我告诉你方法,我用于错误记录的方法是这样的。 这样你就可以通过代码来处理所有的 vue 错误了。
window.onerror = function (message, source, lineno, colno, error) {
/// what you want to do with error here
};
这是浏览器的全局错误处理程序。如果有任何错误未被发现,可以通过这个来处理。
另外,如果你想处理你的错误。你可以这样做。
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
// when you throw error this will also fetch error.
throw error;
});
如果你想在 vue 上寻找错误处理,你可以去。 https://vuejs.org/v2/api/#errorHandler
Vue.config.errorHandler = function (err, vm, info) {
// handle error
// `info` is a Vue-specific error info, e.g. which lifecycle hook
// the error was found in. Only available in 2.2.0+
}
让我给你一个使用 window.onerror 的链接
【讨论】:
有你的蛋糕,也吃吧。假设您已经在使用interceptor...
axios.interceptors.response.use(function (response) {
return response;
}, function (error) {
store.commit('ERROR', error) // just taking some guesses here
return Promise.reject(error) // this is the important part
})
这将使承诺拒绝返回给调用者,因此在您的组件中,类似于...
axios.whatever(...).then(res => {
// happy days
}, err => {
// oh noes!
})
【讨论】:
return Promise.reject(error) 遇到了Uncaught (in promise) TypeError: Cannot read property 'version' of undefined 错误
return Promise.reject(error) // this is the important part的人吗?哈哈我应该导入Promise吗?
我得出的结论是,它们并不总是存在处理错误的通用方法,因此它们必须以某种方式与上下文耦合。拥有单独的 api 文件是一件好事,但要通过上面提到的来调解这一点。 我有单独的 api 文件,我正在执行以下操作:
//comments-api.js
export default {
get (url, handler){
//return the promise to further possible chains
return axios.get(url)
.then( response => handler.success(response.data) )
.catch( error => handler.serverDownOrUnexpected(error.response) )
},
}
//comments.js - vuex module
import $comments from './../../services/api/comments-api'
...
actions: {
$comments.get(url, {
success: (data) => commit('success_handler', data),
serverDownOrUnexpected: (error) => commit('unexpected', error)
//so on...
})
}
...
在这种方法中,每当我想更改某些错误的处理方式时,我必须只在一个地方进行更改,再加上解耦代码的好处。
【讨论】:
vue 方法(mycomponent.js)
async YourAsyncMethod() {
const payload = {key: "var"}
const result = await axios
.post('/your/api/endpoint', payload)
.catch(e => {
console.log(e.message)
});
}
yourMethod() {
// start axios logic
const payload = {key: "var"}
axios
.post('/your/api/endpoint', payload)
.then(response => {
console.log(response.data)
// start state action logic
this.$store
.dispatch('yourAction', payload)
.then(add => {
console.log('success mutation!');
})
.catch(error => {
// error = Error object,
console.log('error mutation:',error.message);
console.log(error) // to se full error object
});
})
.catch(error => {
console.log('error axios request', error.data)
});
}
带有状态动作 (store/actions.js)
yourAction(){
const some_logic = false;
if (!some_logic) {
// when return a Promisse.reject
//you can get error with catch(e) from youtMethod
return Promise.reject(new Error("Impressora já adicionada"))
}
context.commit('MUTATION_METHOD', payload);
}
用 axios
http
.post('/your/api/endpoint', payload)
.then(response => {
console.log(response.data)
})
.catch(error => {
console.log('error', error.data)
});
【讨论】:
你可以像这样使用事件总线
import Vue from 'vue'
export const EventBus = new Vue();
然后触发错误
axios.get(...)
.catch(function (error) {
EventBus.$emit('error', error)
});
【讨论】:
我只是用catch。我在切换到 vuex 之前使用的是同样的东西。这可能是最通用且有据可查的解决方案,让我可以像以前一样继续将错误插入到组件的 html 中。它还让我继续使用我的 loading = true, loading = false html 动画。
所以我最终得到了 3 个状态属性、数据、错误和加载。它似乎对我有用。你的旅费可能会改变。我也在使用 vuex 模块和命名空间,但这是一个没有它的简化示例
//somevuexstore.js
actions: {
fetchData(context) {
axios
.get("api/someendpoint")
.then(response => {
context.commit('loading')
context.commit('organizations', response.data)
}).catch(error => {
console.log(error.response.data.message || error.message)
context.commit('error', error)
});
},
mutations: {
organizations(state, data) {
return state.organization = data
},
error(state, data) {
return state.error = data
},
loading(state) {
return state.loading = false
},
state= {
organization: [],
error: '',
loading: true
}
然后在我的 component.vue 中,它与我之前的做法非常相似,只是添加了计算属性。
computed: {
...mapState({
getError: 'error',
getLoading: 'loading',
getAllOrg: 'organization',
}),
}
mounted() {
this.$store.dispatch('fetchData')
}
我的 html 会是这样的。
<tr v-for="value in getAllOrg" :key="value.id">
<td>{{ value.id }}</td>
<td>{{ value.email }}</td>
<td>{{ value.name }}</td>
<td>{{ value.['created-at'] | formatDate }}</td>
</tr>
我在适当的地方插入错误消息
<div v-if="getError" class="error">
<p>{{ getError }}</p>
</div>
对于加载动画,我使用vue spinners 包在适当的地方插入到 html 中。
<div v-if="getLoading" style="height:37px;">
<p>
<bar-loader class="custom-class" color="#c2c2c2"
getLoading="getLoading"
:width="130"></bar-loader>
</p>
【讨论】:
在 Vuex 中添加“最后加载”状态,并观察 root 的变化。
这可能看起来繁重而复杂,但它是合乎逻辑的并且可以很好地分离组件。
奖励:您会立即知道您是否已加载数据并且尝试是否成功!
【讨论】:
import {onErrorCaptured, ref} from "vue";
setup(){
let errors = ref(null)
onErrorCaptured((error)=>{
// checking for server response first
errors.value = error.response?Object.values(error.response.data)[0]:error.message
})
return{errors}
}
【讨论】: