Bind Progress Bars to Axios Lifecycle Events

Integrating visual progress indicators like NProgress with Axios improves user experience by delivering immediate feedback during asynchronous HTTP operations. This article details the primary techniques for binding progress bars to Axios lifecycle events, covering global interceptors, concurrent request management via active request counting, and handling granular download/upload progress events.

Global Request and Response Interceptors

The most common technique for binding NProgress to Axios is using Axios interceptors. Interceptors hook directly into the lifecycle of HTTP requests right before they are dispatched and immediately after a response or error is received.

import axios from 'axios';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

// Configure NProgress options if needed
NProgress.configure({ showSpinner: false });

// Bind to request lifecycle
axios.interceptors.request.use(
  (config) => {
    NProgress.start();
    return config;
  },
  (error) => {
    NProgress.done();
    return Promise.reject(error);
  }
);

// Bind to response lifecycle
axios.interceptors.response.use(
  (response) => {
    NProgress.done();
    return response;
  },
  (error) => {
    NProgress.done();
    return Promise.reject(error);
  }
);

Managing Concurrent Requests with Request Counters

When multiple API requests occur simultaneously, the standard interceptor approach causes the progress bar to terminate prematurely as soon as the first request finishes. To resolve this, use an active request counter to ensure NProgress.done() is only called when all pending network calls have settled.

import axios from 'axios';
import NProgress from 'nprogress';

let activeRequests = 0;

const calculateProgress = () => {
  if (activeRequests === 0) {
    NProgress.done();
  }
};

axios.interceptors.request.use(
  (config) => {
    if (activeRequests === 0) {
      NProgress.start();
    }
    activeRequests++;
    return config;
  },
  (error) => {
    activeRequests--;
    calculateProgress();
    return Promise.reject(error);
  }
);

axios.interceptors.response.use(
  (response) => {
    activeRequests--;
    calculateProgress();
    return response;
  },
  (error) => {
    activeRequests--;
    calculateProgress();
    return Promise.reject(error);
  }
);

Granular Progress with Upload and Download Hooks

For large payloads or file transfers, indeterminate progress bars do not reflect actual data transfer states. Axios provides onUploadProgress and onDownloadProgress configuration options that expose the native browser progress events.

You can bind these events to NProgress.set(percentage) to reflect real-time byte completion:

import axios from 'axios';
import NProgress from 'nprogress';

export const uploadFile = (file) => {
  const formData = new FormData();
  formData.append('file', file);

  NProgress.start();

  return axios.post('/api/upload', formData, {
    onUploadProgress: (progressEvent) => {
      if (progressEvent.total) {
        const percentCompleted = progressEvent.loaded / progressEvent.total;
        NProgress.set(percentCompleted);
      }
    },
  }).finally(() => {
    NProgress.done();
  });
};

Scoped Axios Instances

To prevent internal or polling requests from triggering the progress bar across the entire application, bind NProgress strictly to dedicated Axios instances rather than the global axios object.

import axios from 'axios';
import NProgress from 'nprogress';

// Create an isolated instance for user-driven UI actions
const apiClient = axios.create({
  baseURL: 'https://api.example.com',
});

apiClient.interceptors.request.use((config) => {
  NProgress.start();
  return config;
});

apiClient.interceptors.response.use(
  (response) => {
    NProgress.done();
    return response;
  },
  (error) => {
    NProgress.done();
    return Promise.reject(error);
  }
);

export default apiClient;

By leveraging scoped instances, request counters, and transfer progress hooks, NProgress integrates cleanly with Axios while preventing visual glitches during complex network interactions.