<div class="container">

  <h1>Global HTTP request and response handling with the Axios interceptors</h1>

  <p>This Pen is an example of how to globally catch requests, responses and errors by <a href="https://github.com/axios/axios#interceptors" target="_blank" rel="noopener noreferrer">Axios interceptor</a>.<p>

  <button class="btn btn--success js-call-success">Call success</button>
  <button class="btn btn--warning js-call-failure">Call failure</button>
  <hr>
  <button class="btn btn--small btn--disabled js-enable-handler" disabled>Enable handlers</button>
  <button class="btn btn--small js-disable-handler">Disable handlers</button>
</div>

<p>Read more: <a href="https://auralinna.blog/post/2019/global-http-request-and-response-handling-with-the-axios-interceptor" target="_blank">Global HTTP request and response handling with the Axios interceptor</a></p>
$success-color: #4f9b31;
$warning-color: #bd3f1d;
$disabled-color: #888;

html, body {
  color: #333;
  font-size: 16px;
  line-height: 20px;
}
body {
  margin: 20px;
  text-align: center;
}

h1 {
  line-height: 1.2;
  margin-bottom: 24px;
}

.container {
  display: block;
  margin: 0 auto 20px;
  max-width: 640px;
}

/** Buttons */

.btn {
  background: #57a1a6;
  border: 0;
  border-radius: 4px;
  box-shadow: #073f43 2px 3px 0px 0px;
  color: #fff;
  display: inline-block;
  font-size: 1.5rem;
  font-weight: bold;
  margin: 10px;
  padding: 12px 24px;
  transition: 0.1s all ease-in-out;
  
  &:active {
    box-shadow: #0e474b 1px 1px 0px 0px;
    transform: translate(2px, 3px);
  }
}

.btn--small {
  font-size: 1rem;
  font-weight: normal;
  padding: 8px 16px;
}

.btn--success {
  background: $success-color;
  box-shadow: darken($success-color, 20) 2px 3px 0px 0px;
  &:active {
    box-shadow: darken($success-color, 20) 1px 1px 0px 0px;
  }
}

.btn--warning {
  background: $warning-color;
  box-shadow: darken($warning-color, 20) 2px 3px 0px 0px;
  &:active {
    box-shadow: darken($warning-color, 20) 1px 1px 0px 0px;
  }
}

.btn--disabled {
  background: $disabled-color;
  box-shadow: darken($disabled-color, 20) 2px 3px 0px 0px;
  cursor: not-allowed;
  &:active {
    box-shadow: darken($disabled-color, 20) 2px 3px 0px 0px;
    transform: none;
  }
}

/** VanillaToasts customization */

.vanillatoasts-toast {
  text-align: left;
}

.vanillatoasts-text {
  overflow: hidden;
}

.vanillatoasts-success {
  border-color: $success-color
}

.vanillatoasts-warning {
  border-color: $warning-color;
}
const TIMEOUT = 4000
const isHandlerEnabled = (config={}) => {
  return config.hasOwnProperty('handlerEnabled') && !config.handlerEnabled ? 
    false : true
}

const requestHandler = (request) => {
  if (isHandlerEnabled(request)) {
    request.headers['X-CodePen'] = 'https://codepen.io/teroauralinna/full/vPvKWe'
    VanillaToasts.create({
      title: 'Sending request',
      text: `Sending request to: ${request.url}`,
      type: 'info',
      timeout: TIMEOUT
    })
  }
  return request
}

const errorHandler = (error) => {
  if (isHandlerEnabled(error.config)) {
    VanillaToasts.create({
      title: `Request failed: ${error.response.status}`,
      text: `Unfortunately error happened during request: ${error.config.url}`,
      type: 'warning',
      timeout: TIMEOUT
    })
  }
  return Promise.reject({ ...error })
}

const successHandler = (response) => {
  if (isHandlerEnabled(response.config)) {
    VanillaToasts.create({
      title: 'Request succeeded!',
      text: `Request done successfully: ${response.config.url}`,
      type: 'success',
      timeout: TIMEOUT
    })
  }
  return response
}

const makeSuccessCall = async (handlerEnabled) => {
  try {
    await axiosInstance.get('/v2/5c94c4423600001818941c8b?mocky-delay=300ms', {
      handlerEnabled
    })
  } catch (error) {
    console.error(error)
  }
}

const makeFailureCall = async (handlerEnabled) => {
  try {
    await axiosInstance.get('/v2/5c94c4793600001818941c8f?mocky-delay=300ms', {
      handlerEnabled
    })
  } catch (error) {
    console.error(error)
  }
}

const toggleButtons = (enabled) => {
  handlerEnabled = !enabled
  const disableBtn = document.querySelector('.js-disable-handler')
  const enableBtn = document.querySelector('.js-enable-handler')
  disableBtn.classList.toggle('btn--disabled')
  disableBtn.disabled = !handlerEnabled
  enableBtn.classList.toggle('btn--disabled')
  enableBtn.disabled = handlerEnabled 

  VanillaToasts.create({
    title: `Handlers ${handlerEnabled ? 'enabled' : 'disabled'}`,
    text: `Handlers are now ${handlerEnabled ? 'enabled' : 'disabled'}. ${handlerEnabled ? 'You\'ll see request notifications.' : 'You won\'t see request notifications.'}`,
    type: 'info',
    timeout: TIMEOUT
  })
}

// Init Axios
const axiosInstance = axios.create({
  baseURL: 'https://www.mocky.io/'
})

// Add interceptors
axiosInstance.interceptors.request.use(
  request => requestHandler(request)
)

axiosInstance.interceptors.response.use(
  response => successHandler(response),
  error => errorHandler(error)
)

let handlerEnabled = true

// Add events to the buttons
const buttons = document.querySelectorAll('button')
const buttonActions = [
  { 
    selector: '.js-call-success', 
    callback: () => makeSuccessCall(handlerEnabled)
  },
  { 
    selector: '.js-call-failure', 
    callback: () => makeFailureCall(handlerEnabled)
  },
  { 
    selector: '.js-disable-handler', 
    callback: () => toggleButtons(handlerEnabled)
  },
  { 
    selector: '.js-enable-handler', 
    callback: () => toggleButtons(handlerEnabled)
  }
]

buttonActions.forEach(item => {
  const btn = document.querySelector(item.selector)
  btn.addEventListener('click', item.callback)
})
View Compiled

External CSS

  1. https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap-reboot.min.css
  2. https://cdn.jsdelivr.net/npm/vanillatoasts@1.3.0/vanillatoasts.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.1/axios.min.js
  2. https://cdn.jsdelivr.net/npm/vanillatoasts@1.3.0/vanillatoasts.min.js
  3. https://cdn.jsdelivr.net/npm/vanillatoasts@1.3.0/vanillatoasts.css