Axios 处理错误
Posted
技术标签:
【中文标题】Axios 处理错误【英文标题】:Axios handling errors 【发布时间】:2018-10-02 17:08:01 【问题描述】:我正在尝试使用 Axios 更好地理解 javascript 承诺。我假装是处理 Request.js 中的所有错误,只从任何地方调用请求函数,而不必使用catch()
。
在此示例中,对请求的响应将为 400,并带有 JSON 格式的错误消息。
这是我得到的错误:
Uncaught (in promise) Error: Request failed with status code 400
我找到的唯一解决方案是在 Somewhere.js 中添加.catch(() => )
,但我试图避免这样做。有可能吗?
代码如下:
请求.js
export function request(method, uri, body, headers)
let config =
method: method.toLowerCase(),
url: uri,
baseURL: API_URL,
headers: 'Authorization': 'Bearer ' + getToken() ,
validateStatus: function (status)
return status >= 200 && status < 400
...
return axios(config).then(
function (response)
return response.data
).catch(
function (error)
console.log('Show error notification!')
return Promise.reject(error)
)
Somewhere.js
export default class Somewhere extends React.Component
...
callSomeRequest()
request('DELETE', '/some/request').then(
() =>
console.log('Request successful!')
)
...
【问题讨论】:
你想打破承诺链吗? 不确定。这是否会阻止我在调用请求函数时不必使用 catch? 不成功的状态码在逻辑上是您应用程序中的异常状态吗?您希望调用代码对其做出什么反应? 如果您将错误发送到成功路径,您很可能需要测试它们以便在更高级别分支。我想说让成功成为成功,让错误成为错误,并相应地 .catch()。 【参考方案1】:实际上,到目前为止,axios 是不可能的。只有2xx
范围内的状态码才能被.then()
捕获。
传统的方法是在catch()
块中捕获错误,如下所示:
axios.get('/api/xyz/abcd')
.catch(function (error)
if (error.response)
// Request made and server responded
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
else if (error.request)
// The request was made but no response was received
console.log(error.request);
else
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
);
另一种方法是在请求或响应被 then 或 catch 处理之前拦截它们。
axios.interceptors.request.use(function (config)
// Do something before request is sent
return config;
, function (error)
// Do something with request error
return Promise.reject(error);
);
// Add a response interceptor
axios.interceptors.response.use(function (response)
// Do something with response data
return response;
, function (error)
// Do something with response error
return Promise.reject(error);
);
【讨论】:
为什么你只在你的then
部分和Promise.reject
在你的catch
部分中使用简单的回报?对我来说似乎不太一致。
我使用了来自github官方axios
文档的sn-p。 github.com/axios/axios#interceptors
无论如何,我认为您指的是interceptor
部分,但那里没有then
。请求或响应在被处理之前被拦截,因此,我们还不想@987654333@。但是,如果遇到错误,如果我们愿意,我们可以Promise.reject()
。或者,我们可以返回一些东西,然后在处理请求或响应时,我们可以使用Promise.reject()
。同样的事情。
啊,是的,这很有道理!因此,在我们已经知道的错误情况下,不需要进一步处理请求,因此可以拒绝承诺。
谢谢,伙计!我不知道错误键也有error.request
【参考方案2】:
如果你想访问整个错误正文,如下所示:
async function login(reqBody)
try
let res = await Axios(
method: 'post',
url: 'https://myApi.com/path/to/endpoint',
data: reqBody
);
let data = res.data;
return data;
catch (error)
console.log(error.response); // this is the main part. Use the response property from the error object
return error.response;
【讨论】:
这真的解决了我的问题,谢谢elonaire【参考方案3】:你可以这样: error.response.data 就我而言,我从后端获得了 error 属性。所以,我使用了 error.response.data.error
我的代码:
axios
.get(`$API_BASE_URL/students`)
.then(response =>
return response.data
)
.then(data =>
console.log(data)
)
.catch(error =>
console.log(error.response.data.error)
)
【讨论】:
【参考方案4】:如果你想使用异步等待尝试
export const post = async ( link,data ) =>
const option =
method: 'post',
url: `$URL$link`,
validateStatus: function (status)
return status >= 200 && status < 300; // default
,
data
;
try
const response = await axios(option);
catch (error)
const response = error;
const request, ...errorObject = response; // take everything but 'request'
console.log(errorObject);
【讨论】:
我已经看到 error.response 未定义,然后它将在解构中失败【参考方案5】:我尝试使用trycatch
方法,但它对我不起作用。但是,当我切换到使用.then(...).catch(...)
时,AxiosError 被正确捕获,我可以使用它。当我在设置断点时尝试前者时,它不允许我看到 AxiosError 而是告诉我捕获的错误是未定义的,这也是最终在 UI 中显示的内容。
不知道为什么会发生这种情况,我觉得这很简单。无论哪种方式,我都建议使用上面提到的常规.then(...).catch(...)
方法以避免向用户抛出未定义的错误。
【讨论】:
今天我也遇到了同样的情况:/try..catch
仅适用于 async/await
。您可以使用.catch()
(捕获被拒绝的承诺)或try await axios... catch (err) ...
(捕获被拒绝的承诺导致的异常)来处理它【参考方案6】:
如果我理解正确,您希望仅在请求成功时才调用请求函数的then
,并且您希望忽略错误。为此,您可以创建一个新的 Promise 在 axios 请求成功时解决它,并且在失败的情况下永远不要拒绝它。
更新后的代码如下所示:
export function request(method, uri, body, headers)
let config =
method: method.toLowerCase(),
url: uri,
baseURL: API_URL,
headers: 'Authorization': 'Bearer ' + getToken() ,
validateStatus: function (status)
return status >= 200 && status < 400
return new Promise(function(resolve, reject)
axios(config).then(
function (response)
resolve(response.data)
).catch(
function (error)
console.log('Show error notification!')
)
);
【讨论】:
不会造成内存泄漏吗?用户体验也将是“奇怪的”。无尽的微调器,而不是在页面上的正确位置清除错误消息。猜猜这不是让用户高兴的原因。我投票赞成在您提出请求的每个地方添加诚实的错误处理程序!)【参考方案7】:从任何地方调用请求函数,而无需使用 catch()。
首先,虽然在一个地方处理大多数错误是一个好主意,但请求并不那么容易。应该传递一些错误(例如 400 个验证错误,例如:“用户名被占用”或“无效电子邮件”)。
所以我们现在使用基于 Promise 的函数:
const baseRequest = async (method: string, url: string, data: ?) =>
new Promise< data: any >((resolve, reject) =>
const requestConfig: any =
method,
data,
timeout: 10000,
url,
headers: ,
;
try
const response = await axios(requestConfig);
// Request Succeeded!
resolve(response);
catch (error)
// Request Failed!
if (error.response)
// Request made and server responded
reject(response);
else if (error.request)
// The request was made but no response was received
reject(response);
else
// Something happened in setting up the request that triggered an Error
reject(response);
;
然后你可以像这样使用请求
try
response = await baseRequest('GET', 'https://myApi.com/path/to/endpoint')
catch (error)
// either handle errors or don't
【讨论】:
抱歉吹毛求疵,但有两件事:如果你真的想使用async
将它移到你的 promise resolve/reject 函数前面。或者理想情况下,甚至不用费心使用 Promise(因为您将 baseRequest 包装在异步装饰器中),只需继续您的 try/catch 和错误类型分支,只需使用 return
而不是 resolve
。其次,我喜欢没有服务器响应的测试!但是当axios超时的时候,会不会抛出异常,被当作服务器没有返回响应?还是这些场景是一回事?
感谢airtonix的建议。这个功能已经很老了,我总是很乐意改进代码。此函数中 async/await 和 Promises 的混合并不理想。你能编辑我的评论以反映这些变化吗? RE 您的问题 AFAIK axios 在代码的catch
部分中处理这两个问题。我会手动将超时设置为非常低,以测试我对超时的错误处理。 “缺席服务器”是指 404 错误?还是没有网络错误?全部在 catch 块中处理,因此请尝试自己触发它们进行测试。【参考方案8】:
处理响应类型设置为流的 axios 错误的一种方法对我有用。
.....
.....
try
.....
.....
// make request with responseType: 'stream'
const url = "your url";
const response = axios.get(url, responseType: "stream" );
// If everything OK, pipe to a file or whatever you intended to do
// with the response stream
.....
.....
catch(err)
// Verify it's axios error
if(axios.isAxios(err))
let errorString = "";
const streamError = await new Promise((resolve, reject) =>
err.response.data
.on("data", (chunk) =>
errorString += chunk;
.on("end", () =>
resolve(errorString);
);
// your stream error is stored at variable streamError.
// If your string is JSON string, then parse it like this
const jsonStreamError = JSON.parse(streamError as string);
console.log( jsonStreamError )
// or do what you usually do with your error message
.....
.....
.....
.....
【讨论】:
【参考方案9】:为了可重用性:
创建文件errorHandler.js:
export const errorHandler = (error) =>
const request, response = error;
if (response)
const message = response.data;
const status = response.status;
return
message,
status,
;
else if (request)
//request sent but no response received
return
message: "server time out",
status: 503,
;
else
// Something happened in setting up the request that triggered an Error
return message: "opps! something went wrong while setting up request" ;
;
然后,每当你发现 axios 的错误时:
Just import error handler from errorHandler.js and use like this.
try
//your API calls
catch (error)
const message: errorMessage = errorHandlerForAction(error);
//grab message
【讨论】:
以上是关于Axios 处理错误的主要内容,如果未能解决你的问题,请参考以下文章
避免在每个请求中使用 Axios 在 Vue 中响应错误时进行处理