javascript - 如何使用 Redux Thunk 处理 fetch() 响应中的错误?

标签 javascript redux fetch-api

我正在使用同构 fetch 发出 API 请求,并使用 Redux 来处理我的应用程序的状态。

我想通过触发 Redux 操作来处理互联网连接丢失错误和 API 错误。

我有以下(正在进行的/坏的)代码,但无法找出触发 Redux 操作的正确方法(而不是仅仅抛出错误并停止一切):

export function createPost(data = {}) {

    return dispatch => {

        dispatch(requestCreatePost(data))

        return fetch(API_URL + data.type, {
            credentials: 'same-origin',
            method: 'post',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'X-WP-Nonce': API.nonce
            },
            body: JSON.stringify(Object.assign({}, data, {status: 'publish'}))
        }).catch((err) => {

            //HANDLE WHEN HTTP ISN'T EVEN WORKING
            return dispatch => Promise.all([
                dispatch({type: PRE_FETCH_RESOURCES_FAIL, errorType: 'fatal', message:'Error fetching resources', id: h.uniqueId()}),
                dispatch({type: PRE_CREATE_API_ENTITY_ERROR, errorType: 'fatal', id: h.uniqueId(), message: 'Entity error before creating'})
            ])
        }).then((req) => {

            //HANDLE RESPONSES THAT CONSTITUTE AN ERROR (VIA THEIR HTTP STATUS CODE)
            console.log(req);
            if (!req || req.status >= 400) {
                return dispatch => Promise.all([
                    dispatch({type: FETCH_RESOURCES_FAIL, errorType: 'warning', message:'Error after fetching resources', id: h.uniqueId()}),
                    dispatch({type: CREATE_API_ENTITY_ERROR, errorType: 'warning', id: h.uniqueId(), message: 'Entity error whilst creating'})
                ])
            }
            else {
                return req.json()
            }
        }).then((json) => {
            var returnData = Object.assign({},json,{
                type: data.type
            });
            dispatch(receiveCreatePost(returnData))
        })
    }
}

如果我故意禁用互联网连接,在 JS 控制台中,当我通过 console.log() (如上)登录时,它会输出以下内容: POST http://example.com/post net::ERR_INTERNET_DISCONNECTED(anonymous function) (dispatch) { return Promise.all([dispatch({ type: PRE_FETCH_RESOURCES_FAIL, errorType: 'fatal', message: 'Error fetching resources', id: _CBUtils2.default.uniqueId() }), dispatch({ type:… cb_app_scripts.js?ver=1.0.0:27976 Uncaught (in promise) TypeError: req.json is not a function(…)
如果这是完全错误的,请原谅我,但我不想做任何事情,只是在出现错误时触发两个 Redux Actions(一个一般错误,一个特定于发生错误时我们正在执行的操作)。

我正在努力实现的目标是可能的吗?

似乎(通过我的日志记录到控制台)脚本的“then”部分仍在执行(因为它的内容是我的“catch”调度函数)..

最佳答案

我对几件事感到困惑:

  • 为什么使用 Promise.all围绕调度两个同步 Action ?调用dispatch类似于 {type: PRE_FETCH_RESOURCES_FAIL, ...}不会返回 Promise,所以 Promise.all是不必要的。 Promise.all()仅当您调度的操作本身被编写为 thunk 操作创建者时才有用,这里不是这种情况。
  • return dispatch => ...仅在 Action 创建者的一开始就需要一次。无需在 catch 中重复此操作。或 then block ——事实上,重复它会使内部代码根本不执行。这是一种注入(inject)dispatch的方法在顶层进入你的函数,重复它是没有意义的。
  • 如果你把 thencatch 之后,即使在捕获到错误后它也会运行。这不是您想要的行为——在错误处理程序之后立即运行成功处理程序是没有意义的。您希望它们是两个单独的代码路径。
  • 次要命名 nitpick:您将响应称为“req ”。应该是res .

  • 感觉就像你对 Redux Thunk 的工作原理有一个错误的心理模型,并且试图将不同示例的部分组合在一起直到它点击。随机缩进也导致这段代码有点难以理解。

    这在 future 会很痛苦,所以我建议获得一个更完整的关于 Redux Thunk 所做的心智模型,return dispatch => ...意味着,以及 Promises 如何融入图片。我会将此答案推荐为 in-depth introduction to Redux Thunk .

    如果我们解决了这些问题,您的代码应该大致如下所示:
    export function createPost(data = {}) {
      return dispatch => {
        dispatch(requestCreatePost(data));
    
        return fetch(API_URL + data.type, {
          credentials: 'same-origin',
          method: 'post',
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'X-WP-Nonce': API.nonce
          },
          body: JSON.stringify(Object.assign({}, data, {status: 'publish'}))
        })
        // Try to parse the response
        .then(response =>
          response.json().then(json => ({
            status: response.status,
            json
          })
        ))
        .then(
          // Both fetching and parsing succeeded!
          ({ status, json }) => {
            if (status >= 400) {
              // Status looks bad
              dispatch({type: FETCH_RESOURCES_FAIL, errorType: 'warning', message:'Error after fetching resources', id: h.uniqueId()}),
              dispatch({type: CREATE_API_ENTITY_ERROR, errorType: 'warning', id: h.uniqueId(), message: 'Entity error whilst creating'})
            } else {
              // Status looks good
              var returnData = Object.assign({}, json, {
                  type: data.type
              });
              dispatch(receiveCreatePost(returnData))
            }
          },
          // Either fetching or parsing failed!
          err => {
            dispatch({type: PRE_FETCH_RESOURCES_FAIL, errorType: 'fatal', message:'Error fetching resources', id: h.uniqueId()}),
            dispatch({type: PRE_CREATE_API_ENTITY_ERROR, errorType: 'fatal', id: h.uniqueId(), message: 'Entity error before creating'})
          }
        );
      }
    }
    

    关于javascript - 如何使用 Redux Thunk 处理 fetch() 响应中的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37078215/

    相关文章:

    javascript - 如何将 "tags"与 Select2 一起使用

    javascript - 如何循环遍历 Firebase 集合并为每个集合添加独特的颜色?

    reactjs - 处理来自输入文件的文件并稍后上传 react redux

    javascript - 如何使用 fetch api 从 json 中的先前值获取值?

    javascript - 如何从函数返回获取 API 结果?

    javascript - 如何将二维复选框名称解析为具有匹配索引的 JSON?

    javascript - 在 Firefox 扩展中使用 indexedDB

    javascript - 我应该使用 connect 还是 hooks 来进行 React Redux,哪个性能更好?

    javascript - 为什么状态更新后 store.subscribe() 没有触发?

    c++ - C++ 类中的成功回调 Emscripten FETCH API