Axios处理错误

我试图用Axios更好地理解javascript承诺。我假装处理request .js中的所有错误,只从任何地方调用请求函数,而不必使用catch()

在本例中,对请求的响应将是400,并带有一个JSON格式的错误消息。

这是我得到的错误:

Uncaught (in promise) Error: Request failed with status code 400

我找到的唯一解决方案是在Somewhere.js中添加.catch(() => {}),但我试图避免这样做。这可能吗?

代码如下:

Request.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!')
}
)
}


...


}
627854 次浏览

实际上,这在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);
}


});

另一种方法是在请求或响应被处理或捕获之前拦截它们。

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);
});

如果你不想使用异步等待尝试

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);
}

从任何地方调用请求函数,而不必使用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 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;
}


}
你可以这样做: error.response.data < br > 在我的例子中,我从后端获得了错误属性。因此,我使用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)
})

我尝试使用try{}catch{}方法,但它不适合我。然而,当我切换到使用.then(...).catch(...)时,AxiosError被正确捕获,我可以使用它。当我在设置断点时尝试前者时,它不允许我看到AxiosError,而是告诉我捕获的错误是未定义的,这也是最终在UI中显示的错误。

不知道为什么会这样,我觉得这很微不足道。由于这个原因,我建议使用上面提到的常规.then(...).catch(...)方法来避免向用户抛出未定义的错误。

如果我理解正确,您希望请求函数的then只在请求成功时被调用,并且您希望忽略错误。为此,您可以创建一个新的承诺,在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!')
}
)
});


}

处理响应类型集到流的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
.....
.....
}
.....
.....
}
   

  

可重用性:

创建一个文件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
}

https://stackabuse.com/handling-errors-with-axios/

    let res = await axios.get('/my-api-route');


// Work with the response...
} catch (err) {
if (err.response) {
// The client was given an error response (5xx, 4xx)
} else if (err.request) {
// The client never received a response, and the request was never left
} else {
// Anything else
}
}
try {
let res = await axios.get('/my-api-route');


// Work with the response...
} catch (err) {
if (err.response) {
// The client was given an error response (5xx, 4xx)
} else if (err.request) {
// The client never received a response, and the request was never left
console.log(err.request);
} else {
// Anything else
}
}

如果我理解正确的话,您需要某种全局处理程序,这样就不必为所发出的每个请求附加一个catch处理程序。有一个名为unhandledrejection的窗口事件。

你可以在官方文档中阅读有关此事件的更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Window/unhandledrejection_event

下面是如何为这个事件附加一个监听器:

window.addEventListener('unhandledrejection', (event) => {
// Handle errors here...
});

使用Promise catch方法处理API错误

let url = ``
axios.get(url)
.then((response) => {
// Success
})
.catch((error) => {
// Error
if (error.response) {
// 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
// `error.request` is an instance of XMLHttpRequest in the
// browser and an instance of
// HTTP.ClientRequest in node.js
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
}
console.log(error.config);
});