簡體   English   中英

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

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

我嘗試使用redux-saga處理來自服務器的Unauthorized錯誤。 這是我的傳奇:

function* logIn(action) {
  try {
    const user = yield call(Api.logIn, action);
    yield put({type: types.LOG_IN_SUCCEEDED, user});
  } catch (error) {
    yield put({type: types.LOG_IN_FAILED, error});
  }
}

我獲取這樣的數據:

fetchUser(action) {
  const {username, password} = action.user;
  const body = {username, password};
  return fetch(LOGIN_URL, {
    method,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body)
  })
    .then(res => {
      res.json().then(json => {
        if (res.status >= 200 && res.status < 300) {
          return json
        } else {
          throw res
        }
      })
    })
    .catch(error => {throw error});
}

但是當我期望{type: 'LOG_IN_FAILED', error: 'Unauthorized'}{type: 'LOG_IN_SUCCEEDED', user: undefined}結果是{type: 'LOG_IN_SUCCEEDED', user: undefined} {type: 'LOG_IN_FAILED', error: 'Unauthorized'} 我的錯誤在哪里? 如何使用Redux-Saga正確處理錯誤?

不要處理你的fetchUser方法和你的傳奇中的thenerror 因為你已經try / catch你的傳奇,你可以在那里處理它。

冒險故事

function* logIn(action) {
  try {
    const response = yield call(Api.logIn, action);

    if (response.status >= 200 && response.status < 300) {
      const user = yield response.json();

      yield put({ type: types.LOG_IN_SUCCEEDED, user });
    } else {
      throw response;
    }
  } catch (error) {
    yield put({ type: types.LOG_IN_FAILED, error });
  }
}

fetchUser(action) {
  const { username, password } = action.user;
  const body = { username, password };

  return fetch(LOGIN_URL, {
    method,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body)
  })
}

作為一個方面說明:我覺得fetch的API有點尷尬,因為它返回一個then當你的請求響應-able。 那里有很多圖書館; 我個人更喜歡axios默認返回json。

如果你想要if語句驗證響應狀態if(res.status >= 200 && res.status < 300) {你需要在你的第一個承諾中定義res,那么它當前在res.json()的已解決的承諾中res.json()

.then(res => {
   if (res.status >= 200 && res.status < 300) {
      res.json().then(json => {
         return json
    }
  })
})

如果你需要在一個saga中進行多個API調用,更好的方法是在fetch階段拋出錯誤:

export const getCounterTypes = (user) => {
  const url = API_URL + `api/v4/counters/counter_types`;

  const headers = {
    'Authorization': user.token_type + ' ' + user.access_token,
    'Accept': 'application/json'
  };
  const request = {
      method: 'GET',
      headers: headers
  };
  return fetch(url, request)
  .then(response => {
    return new Promise((resolve, reject) => {
      if (response.status === 401) {
        let err = new Error("Unauthorized");
        reject(err);
      }
      if (response.status === 500) {
        let err = new Error("Critical");
        reject(err);
      }
      if ((response.status >= 200 && response.status < 300) || response.status === 400) {
        response.json().then(json => {
          console.log(json);
          resolve(json);
        });
      }
    });
  });
} 

SAGA

export function* getMainScreenInfoSaga() {
  try {
    const user = yield select(getUser);
    const userInfo = yield select(getUserInfo);
    if (userInfo) {
      yield put({ type: types.NET_LOAD_USER_DATA });
    } else {
      yield put({ type: types.NET_INIT });
    }
    const info = yield all({
      user: call(getInfo, user),
      apartments: call(getUserApartments, user),
      accounts: call(getUserAccounts, user),
      counters: call(getCounters, user)
    });
    const ui = yield select(getUi);
    if (!ui) {
      yield put({ type: types.NET_LOAD_UI });
      const ui = yield all({
        apartmentTypes: call(getApartmentTypes, user),
        serviceTypes: call(getServiceTypes, user),
        counterTypes: call(getCounterTypes, user),
      });
      yield put({ type: types.GET_UI_SUCCESS, ui });
    }
    yield put({ type: types.GET_MAIN_SCREEN_INFO_SUCCESS, info });
    yield put({ type: types.NET_END });

  } catch (err) {

    if (err.message === "Unauthorized") {
      yield put({ type: types.LOGOUT });
      yield put({ type: types.NET_END });
    }
    if (err.message === "Critical") {
      window.alert("Server critical error");
      yield put({ type: types.NET_END });
    }

  }
}

暫無
暫無

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

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