如何在 redux saga catch 方法中获取 axios 错误响应
How to get axios error response INTO the redux saga catch method
使用 axios 的代码是:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => err);
}
然后我将它与 redux-saga 一起使用,如下所示:
function* createBlaBlaFlow(action) {
try {
const response = yield call(createBlaBla, action.payload);
if (response) {
yield put({
type: CREATE_BLA_BLA_SUCCESS
});
}
} catch (err) {
// I need the error data here ..
yield put({
type: CREATE_BLA_BLA_FAILURE,
payload: 'failed to create bla-bla'
});
}
}
如果后端出现一些错误——比如发送到后端的无效数据——它 return 是一个包含一些数据的 400 响应:
{
"code":"ERR-1000",
"message":"Validation failed because ..."
"method":"POST",
"errorDetails":"..."
}
但是我没有在 saga 中的 catch
语句中收到这些有用的数据。我可以 console.log() axios catch
语句中的数据,也可以在 saga 的 try
语句中获取它,但它永远不会到达 catch
中。
可能我需要做点别的事情? ... 或者在这种情况下服务器不应该 return 400 响应?
所以,我想出了两个解决这个问题的方法。
===
第一个 - 非常简单的解决方法,但实际上在某些特定情况下它会很方便。
在 saga 中,就在我们调用带有 axios 调用的函数之前,我们有一个错误变量和一个设置该变量的回调:
let errorResponseData = {};
const errorCallback = (usefulErrorData) => {
errorResponseData = usefulErrorData;
};
然后 - 在 axios 方法中我们有这个:
export const createBlaBla = (payload, errCallback) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => {
if (err && err.response.data && typeof errCallback === 'function') {
errCallback(err.response.data);
}
return err;
});
}
这样,当我们发出请求和后端 returns 错误时 - 我们将调用回调并提供来自后端的错误。这样 - 在传奇中 - 我们在变量中有错误并且可以根据需要使用它。
===
但是,我从另一个论坛找到了另一个解决方案。
我遇到的问题是因为在带有 axios 调用的方法中我有 catch
,这意味着错误不会在生成器中冒泡。所以 - 如果我们像这样使用 axios 调用修改方法:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
}
然后在 saga 的 catch
语句中,我们将得到实际的后端错误。
希望这对其他人有帮助:)
在您的 API 调用中,您可以执行以下操作:
const someAPICall = (action) => {
return axios.put(`some/path/to/api`, data, {
withCredentials: true,
validateStatus: (status) => {
return (status == 200 || status === 403);
}
});
};
请注意 validateStatus()
部分 - 这样当 axios 遇到 200
或 403
响应时,它不会抛出错误,您将能够在
const response = yield call(someAPICall, action);
if (response.status === 200) {
// Proceed further
} else if (response.status === 403) {
// Inform user about error
} else {
...
}
使用 axios 的代码是:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => err);
}
然后我将它与 redux-saga 一起使用,如下所示:
function* createBlaBlaFlow(action) {
try {
const response = yield call(createBlaBla, action.payload);
if (response) {
yield put({
type: CREATE_BLA_BLA_SUCCESS
});
}
} catch (err) {
// I need the error data here ..
yield put({
type: CREATE_BLA_BLA_FAILURE,
payload: 'failed to create bla-bla'
});
}
}
如果后端出现一些错误——比如发送到后端的无效数据——它 return 是一个包含一些数据的 400 响应:
{
"code":"ERR-1000",
"message":"Validation failed because ..."
"method":"POST",
"errorDetails":"..."
}
但是我没有在 saga 中的 catch
语句中收到这些有用的数据。我可以 console.log() axios catch
语句中的数据,也可以在 saga 的 try
语句中获取它,但它永远不会到达 catch
中。
可能我需要做点别的事情? ... 或者在这种情况下服务器不应该 return 400 响应?
所以,我想出了两个解决这个问题的方法。
===
第一个 - 非常简单的解决方法,但实际上在某些特定情况下它会很方便。
在 saga 中,就在我们调用带有 axios 调用的函数之前,我们有一个错误变量和一个设置该变量的回调:
let errorResponseData = {};
const errorCallback = (usefulErrorData) => {
errorResponseData = usefulErrorData;
};
然后 - 在 axios 方法中我们有这个:
export const createBlaBla = (payload, errCallback) => {
return axios.post('/some-url', payload)
.then(response => response)
.catch(err => {
if (err && err.response.data && typeof errCallback === 'function') {
errCallback(err.response.data);
}
return err;
});
}
这样,当我们发出请求和后端 returns 错误时 - 我们将调用回调并提供来自后端的错误。这样 - 在传奇中 - 我们在变量中有错误并且可以根据需要使用它。
===
但是,我从另一个论坛找到了另一个解决方案。
我遇到的问题是因为在带有 axios 调用的方法中我有 catch
,这意味着错误不会在生成器中冒泡。所以 - 如果我们像这样使用 axios 调用修改方法:
export const createBlaBla = (payload) => {
return axios.post('/some-url', payload)
}
然后在 saga 的 catch
语句中,我们将得到实际的后端错误。
希望这对其他人有帮助:)
在您的 API 调用中,您可以执行以下操作:
const someAPICall = (action) => {
return axios.put(`some/path/to/api`, data, {
withCredentials: true,
validateStatus: (status) => {
return (status == 200 || status === 403);
}
});
};
请注意 validateStatus()
部分 - 这样当 axios 遇到 200
或 403
响应时,它不会抛出错误,您将能够在
const response = yield call(someAPICall, action);
if (response.status === 200) {
// Proceed further
} else if (response.status === 403) {
// Inform user about error
} else {
...
}