javascript - 如何对 axios 响应拦截器进行自定义错误代码检查?
问题描述
我在我的应用程序中使用了 graphql,它错误地发送了以下响应。
您可能已经注意到,graphql 将所有错误作为状态码 200 发送。我从 API 返回的错误在data.errors
.
{
"data": {
"errors": [
{
"message": "Error: Token has expired",
"locations": [
{
"line": 3,
"column": 7
}
],
"path": [
"createGame"
],
"extensions": {
"code": "403",
"exception": {
"stacktrace": [
"Error: Error: Token has expired"
]
}
}
}
],
"data": {
"createGame": null
}
},
"status": 200,
"statusText": "OK",
"headers": {
"content-type": "application/json; charset=utf-8"
},
"config": {
"url": "http://localhost:4200/graphql",
"method": "post",
"data": "{\"query\":\"\\n mutation {\\n createGame (name: \\\"SA\\\", shortName: \\\"s\\\") {\\n id,\\n name,\\n shortName\\n }\\n }\\n \"}",
"headers": {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json",
"authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoxLCJlbXBsb3llZUlkIjowLCJ1c2VyUm9sZUlkIjozLCJwYXNzd29yZCI6IiQyYiQxMCRwNTE2V1hnSGZXdWx6czVmY2o2ZGp1Q09lUzF0UUw3U2MySEIuMDRPUmpWekh6VnduSTNwNiIsImlzQWN0aXZlIjp0cnVlLCJjcmVhdGVkQXQiOiIyMDE5LTA4LTE5VDA5OjMxOjA5LjAzOVoiLCJ1cGRhdGVkQXQiOiIyMDE5LTA4LTE5VDA5OjMxOjA5LjA0MVoifSwiaWF0IjoxNTY3ODcyNTk2LCJleHAiOjE1Njc4NzI2MDZ9.HpNE9m5YEUv0qgBHxsEoQMd1p29TkOqvQzYF7ptljJ0"
},
"baseURL": "http://localhost:4200/graphql",
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1
},
"request": {}
}
我遇到的问题是我在前端集成了 axios 响应拦截器
http.interceptors.response.use(
/**
* Leave response as it is.
*/
(response: any) => response,
/**
* This interceptor checks if the response had a 401 status code, which means
* that the access token used for the request has expired. It then refreshes
* the access token and resends the original request.
*/
unauthorizedResponseHandlerInterceptor
);
并且该unauthorizedResponseHandlerInterceptor
函数仅在出现错误时由 Axios 调用,但我的 graphql 服务器将状态返回为 200,因此不会调用该函数。
我有什么办法可以修改 axios 响应拦截器,以便它检查data.errors中的值而不是状态
解决方案
没有错误时调用拦截器的第一个回调。您可以根据 API 发送错误的方式进行一些自定义检查:
http.interceptors.response.use(
/**
* Leave response as it is.
*/
(response: any) => {
if (response.data.errors) {
let customError = new Error(response.data.errors[0].message);
response.original_status = response.status
response.status = response.data.errors[0].extensions.code
customError.response = response;
return Promise.reject(customError);
}
return response;
},
/**
* This interceptor checks if the response had a 401 status code, which means
* that the access token used for the request has expired. It then refreshes
* the access token and resends the original request.
*/
unauthorizedResponseHandlerInterceptor
);
它非常灵活。如上所示,您甚至可以通过Promise.reject()
在拦截器中返回来将成功的调用变成错误。
这是一个可以玩的小提琴:https ://jsfiddle.net/acdcjunior/pvb1kj87/
axios.interceptors.response.use((response) => {
if (response.data.errors) {
let customError = new Error(response.data.errors[0].message);
response.original_status = response.status
response.status = response.data.errors[0].extensions.code
// add some properties to make it look like a regular axios error
customError.response = response;
customError.request = response.request;
customError.config = response.config;
customError.isAxiosError = true; // or not
return Promise.reject(customError);
}
return response;
}, (error) => {
// Do something with response error
return Promise.reject(error);
});
(async () => {
console.log('*** regular axios error:')
await axios.get(`https://example.com/DOESNOTEXIST`)
.then((data) => {
console.log('success -->', data)
})
.catch((e) => {
console.log('error -->', e)
})
console.log('*\n*\n*')
console.log('*** simulating error:')
axios.get(`https://api.myjson.com/bins/d7hbp`)
.then((data) => {
console.log('success -->', data)
})
.catch((e) => {
console.log('error -->', e)
})
})();
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Open dev tools and check the console!
推荐阅读
- android - 过渡管理器延迟过渡不适用于android中的多个视图
- python - 使用斐波那契:暂停执行并从它停止的地方开始的 Python 函数
- reactjs - 异步函数返回承诺对象而不是返回布尔值(reactjs Hooks)
- react-native - 如何在登录屏幕中隐藏底部标签导航?
- r - 如何从 Landsat 图像中提取值并在 R 中绘制不同材料的光谱剖面
- kubernetes - 使用其他属性更新 helm 图表
- javascript - Wordpress 自定义 JS 位置
- visual-studio - 创建应用程序包 CompileXaml 时出错
- mysql - MySQL 疯狂(?)浮点行为
- python - 由于需求错误,无法将一些 refs 推送到 Heroku