簡體   English   中英

如何使用Redux Thunk處理fetch()響應中的錯誤?

[英]How to handle errors in fetch() responses with Redux Thunk?

我正在使用isomorphic 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動作(一般錯誤,一個特定於我們在發生錯誤時執行的操作)。

我正在努力實現的目標是什么?

似乎(通過我的日志記錄到控制台)腳本的'then'部分仍在執行(因為它的內容是我的'catch'調度函數)..

我對幾件事感到困惑:

  1. 為什么使用Promise.all來調度兩個同步動作? 使用{type: PRE_FETCH_RESOURCES_FAIL, ...}等調用dispatch將不會返回Promise,因此Promise.all是不必要的。 Promise.all()僅在您發送的操作本身被寫為thunk動作創建者時才有用,這不是這里的情況。
  2. return dispatch => ...只需要在動作創建者的最開始一次。 沒有必要在重復這個catchthen塊,其實,重復它使內部的代碼不能執行的。 這是一種將dispatch注入到頂級函數中的方法,沒有必要重復它。
  3. 如果你把then一后catch ,它將運行被抓獲錯誤,即使之后。 這不是您想要的行為 - 在錯誤處理程序之后立即運行成功處理程序是沒有意義的。 您希望它們是兩個獨立的代碼路徑。
  4. 次要命名挑剔:您將響應稱為“ req ”。 它可能應該是res

感覺你有一個關於Redux Thunk如何工作的錯誤心智模型,並試圖將不同示例的部分組合在一起直到它點擊。 隨機縮進也有助於此代碼有點難以理解。

這將是一個痛苦的未來,所以我建議得到一個更完整的心理模型Redux Thunk做什么,什么return dispatch => ...意思,以及Promise如何適應圖片。 我會推薦這個答案作為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'})
      }
    );
  }
}

解決方案只是(對於錯誤記錄的兩個實例)替換:

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'})
])```

附:

return 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'}),
Promise.reject(err)
])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM