有没有更好的方法来处理 laravel 和 vue js 的 axios 错误
Posted
技术标签:
【中文标题】有没有更好的方法来处理 laravel 和 vue js 的 axios 错误【英文标题】:is there any better way to handling axios error with laravel and vue js 【发布时间】:2018-08-22 01:46:48 【问题描述】:所以我正在使用 laravel 作为我的后端和 vue js 作为 spa 前端框架来创建 spa 网络应用程序。我正在使用 laravel 护照通过 api 进行身份验证。我正在使用 vuex 来控制我的应用程序状态。
首先我创建一个 api 文件来与 axios 的 api 交互
import BKCU_CONFIG from '../config.js';
export default
getArtikelS: function( p )
return axios.get( BKCU_CONFIG.API_URL + '/artikel' + `?column=$p.column&direction=$p.direction&per_page=$p.per_page&page=$p.page&search_column=$p.search_column&search_operator=$p.search_operator&search_query_1=$p.search_query_1&search_query_2=$p.search_query_2`);
,
getArtikelCUS: function( p, id )
return axios.get( BKCU_CONFIG.API_URL + '/artikel/indexCU/' + id + `?column=$p.column&direction=$p.direction&per_page=$p.per_page&page=$p.page&search_column=$p.search_column&search_operator=$p.search_operator&search_query_1=$p.search_query_1&search_query_2=$p.search_query_2`);
,
getArtikel: function( id )
return axios.get(BKCU_CONFIG.API_URL + '/artikel/' + id);
,
createArtikel: function()
return axios.get(BKCU_CONFIG.API_URL + '/artikel/create');
,
storeArtikel: function ( form )
return axios.post(BKCU_CONFIG.API_URL + '/artikel/store', form);
,
editArtikel: function( id )
return axios.get(BKCU_CONFIG.API_URL + '/artikel/edit/' + id);
,
updateArtikel: function ( id, form )
return axios.post(BKCU_CONFIG.API_URL + '/artikel/update/' + id, form);
,
updateTerbitkan: function( id )
return axios.post(BKCU_CONFIG.API_URL + '/artikel/updateTerbitkan/' + id);
,
updateUtamakan: function( id )
return axios.post(BKCU_CONFIG.API_URL + '/artikel/updateUtamakan/' + id);
,
deleteArtikel: function( id )
return axios.delete(BKCU_CONFIG.API_URL + '/artikel/' + id);
然后我为每个模型创建一个 vuex 模块。像这样的文章:
import ArtikelAPI from '../../api/artikel.js';
export const artikel =
state:
artikelS: [],
artikelLoadStatS: '',
artikel: ,
artikelLoadStat: '',
artikelUpdate: '',
artikelUpdateStat: '',
artikelRules: [],
artikelOption: [],
,
actions:
// load all
loadArtikelS( commit , p )
commit('setArtikelLoadStatS', 'loading');
ArtikelAPI.getArtikelS( p )
.then( function( response )
commit('setArtikelS', response.data.model);
commit('setArtikelLoadStatS', 'success');
)
.catch( error =>
commit('setArtikelS', error.response);
commit('setArtikelLoadStatS', 'fail');
);
,
// load by cu
loadArtikelCUS( commit , [p, id] )
commit('setArtikelLoadStatS', 'loading');
ArtikelAPI.getArtikelCUS( p, id )
.then( function( response )
commit('setArtikelS', response.data.model);
commit('setArtikelLoadStatS', 'success');
)
.catch( error =>
commit('setArtikelS', error.response);
commit('setArtikelLoadStatS', 'fail');
);
,
// load single data
loadArtikel( commit, id )
commit('setArtikelLoadStat', 'loading');
ArtikelAPI.getArtikel( id )
.then( function( response )
commit('setArtikel', response.data );
commit('setArtikelLoadStat', 'success');
)
.catch( error =>
commit('setArtikelS', error.response);
commit('setArtikelLoadStatS', 'fail');
);
,
// create page
createArtikel( commit )
commit('setArtikelLoadStat', 'loading');
ArtikelAPI.createArtikel()
.then( function( response )
commit('setArtikel', response.data.form );
commit('setArtikelRules', response.data.rules);
commit('setArtikelOption', response.data.option)
commit('setArtikelLoadStat', 'success');
)
.catch( function()
commit('setArtikel', []);
commit('setArtikelRules', []);
commit('setArtikelOption', [])
commit('setArtikelLoadStat', 'fail');
);
,
// store data
storeArtikel( commit, state, dispatch, form )
commit('setArtikelUpdateStat', 'loading');
ArtikelAPI.storeArtikel( form )
.then( function( response )
if(response.data.saved)
commit('setArtikelUpdate', response.data);
commit('setArtikelUpdateStat', 'success');
else
commit('setArtikelUpdateStat', 'fail');
)
.catch(error =>
if (error.response.status)
this.errors = error.response.data;
commit('setArtikelUpdate', this.errors);
else
commit('setArtikelUpdate', 'Oops terjadi kesalahan :(');
commit('setArtikelUpdateStat', 'fail');
);
,
// edit page
editArtikel( commit, id )
commit('setArtikelLoadStat', 'loading');
ArtikelAPI.editArtikel( id )
.then( function( response )
commit('setArtikel', response.data.form );
commit('setArtikelRules', response.data.rules);
commit('setArtikelOption', response.data.option)
commit('setArtikelLoadStat', 'success');
)
.catch( function()
commit('setArtikel', []);
commit('setArtikelRules', []);
commit('setArtikelOption', [])
commit('setArtikelLoadStat', 'fail');
);
,
// update data
updateArtikel( commit, state, dispatch, [id, form] )
commit('setArtikelUpdateStat', 'loading');
ArtikelAPI.updateArtikel( id, form )
.then( function( response )
if(response.data.saved)
commit('setArtikelUpdate', response.data);
commit('setArtikelUpdateStat', 'success');
else
commit('setArtikelUpdateStat', 'fail');
)
.catch(error =>
if (error.response.status)
this.errors = error.response.data;
commit('setArtikelUpdate', this.errors);
else
commit('setArtikelUpdate', 'Oops terjadi kesalahan :(');
commit('setArtikelUpdateStat', 'fail');
);
,
updateArtikelTerbitkan( commit, state, dispatch, id )
commit('setArtikelUpdateStat', 'loading');
ArtikelAPI.updateTerbitkan( id )
.then( function( response )
if(response.data.saved)
commit('setArtikelUpdate', response.data);
commit('setArtikelUpdateStat', 'success');
else
commit('setArtikelUpdateStat', 'fail');
)
.catch(error =>
if (error.response.status)
this.errors = error.response.data;
commit('setArtikelUpdate', this.errors);
else
commit('setArtikelUpdate', 'Oops terjadi kesalahan :(');
commit('setArtikelUpdateStat', 'fail');
);
,
updateArtikelUtamakan( commit, state, dispatch, id )
commit('setArtikelUpdateStat', 'loading');
ArtikelAPI.updateUtamakan( id )
.then( function( response )
if(response.data.saved)
commit('setArtikelUpdate', response.data);
commit('setArtikelUpdateStat', 'success');
else
commit('setArtikelUpdateStat', 'fail');
)
.catch(error =>
if (error.response.status)
this.errors = error.response.data;
commit('setArtikelUpdate', this.errors);
else
commit('setArtikelUpdate', 'Oops terjadi kesalahan :(');
commit('setArtikelUpdateStat', 'fail');
);
,
// delete data
deleteArtikel( commit, state, dispatch, id )
commit('setArtikelUpdateStat', 'loading');
ArtikelAPI.deleteArtikel( id )
.then( function( response )
if(response.data.saved)
commit('setArtikelUpdate', response.data);
commit('setArtikelUpdateStat', 'success');
else
commit('setArtikelUpdateStat', 'fail');
)
.catch(error =>
if (error.response.status)
this.errors = error.response.data;
commit('setArtikelUpdate', this.errors);
else
commit('setArtikelUpdate', 'Oops terjadi kesalahan :(');
commit('setArtikelUpdateStat', 'fail');
);
,
// reset status
resetArtikelUpdateStat( commit )
commit('setArtikelUpdateStat', '');
,
mutations:
setArtikelS ( state, artikelS )
state.artikelS = artikelS;
,
setArtikelLoadStatS( state, status )
state.artikelLoadStatS = status;
,
setArtikel ( state, artikel )
state.artikel = artikel;
,
setArtikelLoadStat( state, status )
state.artikelLoadStat = status;
,
setArtikelUpdateStat( state, status )
state.artikelUpdateStat = status;
,
setArtikelUpdate( state, data )
state.artikelUpdate = data;
,
setArtikelRules( state, rules )
state.artikelRules = rules;
,
setArtikelOption( state, option )
state.artikelOption = option;
,
getters:
getArtikelS( state )
return state.artikelS;
,
getArtikelLoadStatS ( state )
return state.artikelLoadStatS;
,
getArtikel( state )
return state.artikel;
,
getArtikelLoadStat ( state )
return state.artikelLoadStat;
,
getArtikelUpdateStat ( state )
return state.artikelUpdateStat;
,
getArtikelUpdate ( state )
return state.artikelUpdate;
,
getArtikelRules ( state )
return state.artikelRules;
,
getArtikelOption ( state )
return state.artikelOption;
如您所见,我的每个操作都包含一个错误捕获,它只捕获错误并显示消息。我发现这种处理方式有一些缺点
也许有人可以帮助我改进这种工作流程,一切正常且非常结构化,但我发现缺少错误捕获,例如:
-
因为我使用的是 laravel,所以我的令牌有时间过期(因为用户离开他们的电脑一段时间或其他事情)所以它会以不太用户友好的方式显示经过身份验证的错误消息,我想要它只需将用户重定向到登录页面以重新登录,然后返回到当前用户所在的页面
我想我在这里做了很多重复的代码,我可以为所有这些 axios 请求做一个单一的错误处理吗?
【问题讨论】:
您可以编写一个通用的拦截器,但您现在的做法的优点是每个都以特定的方式处理错误。如果你写了一个通用的拦截器,你会失去它。 【参考方案1】:你可以使用拦截器。但是,后端应该关心错误并将相应的消息发送给前端。
request.interceptors.response.use(response =>
return response
, error =>
//Put your logic here to manage the error message coming from BE
return Promise.reject(error )
)
如需完整示例,请查看我如何在我的应用中实现整个 axios 实例:
(我已经使用 vuetify 快餐栏组件显示错误信息)
import axios from 'axios'
import store from "../../store/store"
import eventBus from "../main";
const request = axios.create(
baseURL: 'http://localhost:8000'
)
request.interceptors.request.use(request =>
const token = store.state.token
if (token)
request.headers.Authorization = 'Bearer ' + token
return request
, error =>
return Promise.reject(error)
)
request.interceptors.response.use(response =>
return response
, error => //getting error from backend and display it with snackbar(vuetify component)
eventBus.$emit('snackBar',
text: error.response.data.message,
snackbarColor: 'red darken-4'
)
return Promise.reject(error )
)
export default request
使用 Laravel 的示例错误消息:
return response()->json(["message" => "You have not access to perform this action"],403);
【讨论】:
【参考方案2】:你可以使用 axios 的一些特性来摆脱这个样板
使用拦截器
axios.interceptors.response.use(response =>
return response.data;
, error =>
if (error.response && error.response.data)
// handle your errors here.
handleServerErrors(error.response.data);
return Promise.reject(error);
);
使用 axios 默认值
axios.defaults.timeout = 5000;
axios.defaults.baseURL = BKCU_CONFIG.API_URL
不要再连接网址了。由于您已经设置了默认网址,您可以这样做
getArtikel: function( id )
return axios.get('/artikel/' + id);
使用 ES6 特性和 axios 参数,这样你就可以打开它
getArtikelS: function( p )
return axios.get( BKCU_CONFIG.API_URL + '/artikel' + `?column=$p.column&direction=$p.direction&per_page=$p.per_page&page=$p.page&search_column=$p.search_column&search_operator=$p.search_operator&search_query_1=$p.search_query_1&search_query_2=$p.search_query_2`);
,
变成这样更好的东西
getArtikelS(p)
return axios.get(`/artikel`, params: p)
Axios 支持将参数作为对象,因此您不必编写奇怪的查询字符串:)
最后一个提示:不要将所有内容都存储到 vuex 中。如果您不需要超过 1 个组件中的数据,请直接在您的组件中调用 api。
【讨论】:
以上是关于有没有更好的方法来处理 laravel 和 vue js 的 axios 错误的主要内容,如果未能解决你的问题,请参考以下文章
寻找一种更好的方法来使用 Laravel 处理大型 XML 文件以将部分导入 MySQL 数据库