Axios middleware to use in all instances of axios

前端 未结 2 1132
礼貌的吻别
礼貌的吻别 2021-01-08 00:07

I\'m using axios in my react app using import axios from \'axios in many of my scripts. I want to use sort of a middleware that is invoked for all axios calls/e

相关标签:
2条回答
  • 2021-01-08 00:44

    Interceptors are the Axios way of doing this. For me though, it was too limited, tangled in Axios' API, difficult to test, etc.

    Axios-middleware

    So I wrote the axios-middleware module, a simple middleware service that hooks itself in your axios instance (either global or a local one) and provides a simple, self-contained and easily testable middleware API.

    Note: it shines in bigger apps where minimal coupling is really important.

    Simple example

    Here's a simple example from the documentation

    import axios from 'axios';
    import { Service } from 'axios-middleware';
    
    const service = new Service(axios);
    
    service.register({
      onRequest(config) {
        console.log('onRequest');
        return config;
      },
      onSync(promise) {
        console.log('onSync');
        return promise;
      },
      onResponse(response) {
        console.log('onResponse');
        return response;
      }
    });
    
    console.log('Ready to fetch.');
    
    // Just use axios like you would normally.
    axios('https://jsonplaceholder.typicode.com/posts/1')
      .then(({ data }) => console.log('Received:', data));
    

    It should output:

    Ready to fetch.
    onRequest
    onSync
    onResponse
    Received: {userId: 1, id: 1, title: ...
    

    Testing a middleware

    Say we have the following self-contained middleware class that we want to test.

    export default class ApiErrorMiddleware {
      constructor(toast) {
        this.toast = toast;
      }
    
      onResponseError(err = {}) {
        let errorKey = 'errors.default';
        const { response } = err;
    
        if (response && response.status) {
          errorKey = `errors.${response.status}`;
        } else if (err.message === 'Network Error') {
          errorKey = 'errors.network-error';
        }
    
        this.toast.error(errorKey);
        throw err;
      }
    }
    

    Then it's really easy, we don't even need to mock Axios.

    import ApiErrorMiddleware from '@/middlewares/ApiErrorMiddleware';
    
    describe('ApiErrorMiddleware', () => {
      let toast;
      let middleware;
    
      // Jest needs a function when we're expecting an error to be thrown.
      function onResponseError(err) {
        return () => middleware.onResponseError(err);
      }
    
      beforeEach(() => {
        toast = { error: jest.fn() };
        middleware = new ApiErrorMiddleware(toast);
      });
    
      it('sends a code error message', () => {
        hasKey = true;
        expect(onResponseError({ response: { status: 404 } })).toThrow();
        expect(toast.error).toHaveBeenLastCalledWith('errors.404');
      });
    });
    
    0 讨论(0)
  • 2021-01-08 00:46

    As per the documentation - You need to create a file i.e

    // api-client.js
    
    import axios from 'axios';
    
    // Add a request interceptor
    axios.interceptors.request.use(function (config) {
        // Do something before request is sent
        console.log(config);
        return config;
      }, function (error) {
        // Do something with request error
        return Promise.reject(error);
      });
    
    // Add a response interceptor
    axios.interceptors.response.use(function (response) {
        // Do something with response data
        return response;
      }, function (error) {
        // Do something with response error
        return Promise.reject(error);
      });
    
    export default axios;
    

    Then from your container or controller, import above file:

    // Home.js
    import apiClient from './api-client.js';
    
    0 讨论(0)
提交回复
热议问题