如何在 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 遇到 200403 响应时,它不会抛出错误,您将能够在

const response = yield call(someAPICall, action);
if (response.status === 200) {
  // Proceed further
} else if (response.status === 403) {
  // Inform user about error
} else {
  ...
}