如何处理Redux的动作创建者中的Fetch失败

时间:2017-09-08 13:37:37

标签: reactjs redux isomorphic-fetch-api

Redux文档建议每个AJAX请求有3个不同的操作。例如,对于Login,它们将是:

  • LOGIN_REUQEST
  • LOGIN_FAILURE
  • LOGIN_SUCCESS

但是我遇到了fetch可能引发的所有错误的问题。 在redux docs中,我找到了这个例子:

return fetch(`https://www.reddit.com/r/${subreddit}.json`)
  .then(
    response => response.json(),
    // Do not use catch, because that will also catch
    // any errors in the dispatch and resulting render,
    // causing an loop of 'Unexpected batch number' errors.
    // https://github.com/facebook/react/issues/6895
    error => console.log('An error occured.', error)
  )
  .then(json =>
    // We can dispatch many times!
    // Here, we update the app state with the results of the API call.

    dispatch(receivePosts(subreddit, json))
  )

}

但我发现其中有几个问题:

  1. 它没有使用catch,所以它不会在用户端发现AJAX请求的任何问题(例如没有互联网)
  2. 它没有处理状态响应!= 200.
  3. 我最终得到了这段代码,但它仍然无法处理案例#1(因为React问题 - 请参阅上面代码中的评论):

     fetch('/api/auth/signin', {...}),
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json, text/plain, */*',
            }
        })
        .then ( response =>
            response.json().then(json => {
                if (response.ok) {
                    dispatch(loginSuccess(json))
                } else {
                    dispatch(loginFailure(json.errMsg))
                }
            })
         )
    

    您能否给我一个使用fetch处理AJAX请求所有可能错误的示例。许多教程和开源项目都忽略了它。

2 个答案:

答案 0 :(得分:2)

您不需要.catch()来处理离线错误。 .then()的第二个参数,即错误回调,将捕获脱机(无互联网连接)错误。

而且,处理非200的响应非常简单:

fetch({...})
.then(
  response => {
    if (response.status !== 200) {
      dispatch(loginFailed(response.json()));
      return Promise.reject();
    } else {
      return response.json();
    }
  },
  error => {
    dispatch(loginFailed(error.json()));
    return Promise.reject();
  }
)
.then(json => {
  dispatch(loginSuccess(json));
});

答案 1 :(得分:0)

async function fetchLists(url, token, userName, etag, dataToUpdate) {
var responseJSON;
try {
    let response = await fetch(url,
        {
            method: 'GET',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
                'X-Access-Token': token,
                'X-Key': userName,
                'If-None-Match': etag
            }
        }
    );
    switch (response.status) {
        case 200:
            var data = await response.json();
            var dataType = getListForUpdate(dataToUpdate);
            responseJSON = {
                action: dataType,
                message: UPDATE_DATA,
                response: response,
                responseJSON: data
            }
            break;
        case 304:
            var dataType = getListUptoDate(dataToUpdate);
            responseJSON = { action: dataType, message: DATA_UPTO_DATE };
            break;
        case 404:
            responseJSON = { message: NOT_FOUND };
            break;
        case 500:
            responseJSON = { message: SERVER_ERROR };
            break;
        case 401:
        case 402:
            responseJSON = { message: INVALID_CREDENTIALS };
            break;
    }
    // console.log(response);
} catch (err) {
    // console.log(err);
    responseJSON = { message: NETWORK_REQUEST_FAILED };
    // console.log(responseJSON);
}

return responseJSON;
}

此代码结构可能能够解决您的问题。我已经记录了所有响应并留下了网络请求失败的问题。如果您不理解任何评论,请发表评论。

希望它有所帮助。