Handle global error với axios

Đặt vấn đề

Khi mà làm việc với axios chúng ta sẽ luôn cần phải handle error mỗi khi server trả về lỗi hoặc thậm chí không trả về gì, tuy nhiên nếu trong trường hợp các lỗi đấy khá giống nhau thì việc lặp code là điều không thể tránh khỏi. Bài viết này sẽ hướng dẫn các bạn cách xử global error với axios mà tránh việc lặp code

Sử dụng Axios Instance

Đầu tiên các bạn tạo file axios.ts và khởi tạo một instance

import axios, { AxiosError, AxiosResponse } from 'axios';

export const API = axios.create({
  baseURL: '/api',
  timeout: 1000,
});

Viết một Object chuyên xử lý lỗi do axios return

export interface ComposedError {
  readonly message: string;
  readonly error: AxiosError;
  handleGlobally(): void;
  getError(): AxiosError;
}

/**
 * https://medium.com/@ejjay/a-short-ajax-story-on-error-handlers-8baeeccbc062
 */
class ComposedAxiosError implements ComposedError {
  name: string = 'ComposedAxiosError';

  public readonly message: string;

  public readonly error: AxiosError;

  constructor(error: AxiosError) {
    this.error = error;
    const statusCode = error.response ? error.response.status : null;

    switch (statusCode) {
      case 401:
        this.message = 'Please login to access this resource';
        break;
      case 404:
        this.message = 'The requested resource does not exist or has been deleted';
        break;
      default:
        this.message = 'Something went wrong and request was not completed';
    }
  }

  public getError(): AxiosError {
    return this.error;
  }

  public handleGlobally(): void {
    toast.error(this.message); // mình dùng react-toastify để bắn noti lên client
  }
}

Tiếp đó viết một error handler

/**
 * Toast error if server return error
 *
 * @param error
 * @returns
 */
const errorHandler = (error: AxiosError) => {
  const composedError = new ComposedAxiosError(error);
  return Promise.reject(composedError);
};

Một result handler nếu server trả về kết qủa

const resultHandler = (response: AxiosResponse) => {
  if (!response?.data) {
    console.error(`Data is undefined :: [${response.config.url}]`);
    return response;
  }

  return response;
};

Tiếp đó apply chúng vào response interceptor

API.interceptors.response.use(
  resultHandler,
  errorHandler,
);

Done, bước kế tiếp chúng ta dùng API mà khởi tạo ở trên thay vì axios default

Cách sử dụng

import { API } from 'src/lib';

useEffect(() => {
  (async () => {
    try {
      // do your request
    } catch (error) {
      // ignore since error was handled globally
      error.handleGlobally();
    }
  })();

  // Hoặc nếu không muốn dùng handle global error
  try {
    // do your request
  } catch (error) {
    const statusCode = error.response ? error.response.status : null;
    // We will handle locally
    // When it's a 404 error, else handle globally
    if (statusCode === 404) {
      // Do some specific error handling logic for this request
    } else {
      error.handleGlobally();
    }
  }
}, []);

Kết luận

Với cách làm này chúng ta có thể tuỳ ý muốn hay không muốn dùng global error. Như vậy sẽ tiết kiệm khá nhiều thời gian cũng như việc lặp code

Comments

Contact for work:Skype
Code from my 💕