简体   繁体   中英

Handling errors with async await and redux

I want to create a separate class that handles all of my api requests, posts, etc for my redux actions as sometimes done, that way my redux action code is more minimal and doing less work. However, when errors occur, I need to make sure that my actions catch these errors and dispatch them properly to my appropriate reducer. My confusion is that my api function itself is also catching errors, and I am wondering that if an error occurs first, will it first be caught in my api function, and thus I won't catch the error in my action function, thus never dispatching said error? How do I avoid this issue? Can I not catch errors in my api function and instead just divert them somehow to my action? Or do I need to dispatch requestDataFailure to my api function? Thanks.

Action:

export const fetchData = () => async (dispatch) => {
  dispatch(requestData());
  try {
    const json = await ApiClass.getData();
    dispatch(receiveData(json.data));
  } catch (error) {
    dispatch(requestDataFailure(error));
  }
};

Api Class:

import HttpService from './httpServce';

export default class ApiClass {
  static async getData() {
    try {
      const response = await HttpService.get('api/get-data');
      return response.json;
    } catch (error) {
      throw Error(error.message);
    }
  }
}

They will (ultimately) all bubble up to your main method.

In your ApiClass you are essentially rethrowing any error, so that will bubble up into your fetchData function, and will be caught by that block.

You have a few ways of doing this:

  • Keep your try/catch in your ApiClass, and use that for more "friendly" error messages. Take the error from your HttpService.get and maybe read the output of the json from the server (If it's not something like a 500 error), and throw different errors based on the result. For example:
class ProductNotFound extends ApiError {
  constructor(name) {
    super(`This product: '${name}' was not found.`);
  }
}

export default class ApiClass {
  static async getProducts() {
    try {
      const response = await HttpService.get('api/get-products');
      return response.json;
    } catch (error) {
      if (error.code === 404) {
        throw new ProductNotFound();
      }
      // Check if error.response contains valid json, and if so, output a server side message?

      // Unknown error, just throw
      throw ApiUnknownError(error.message);
    }
  }
}

Now you can simply use requestDataFailure and pass the error.message, and display that to the end user.

  • Or, alternatively, you can simply just return response.json; not wrapped in a try/catch block. When HttpService.get rejects, it will throw an error, and you can simply use error.message to get the raw HttpService.get error message from that. Perform any redux actions based on that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM