Обработка повторяющихся HTTP-вызовов в перехватчиках axios

Чтобы обработать повторяющийся запрос Ajax, мы могли бы просто определить переменную загрузки для действий кнопки, которая содержит состояние запроса Ajax. Когда пользователь нажимает кнопку и запускает действие вызова API RESTful, установите для переменной загрузки значение true и отключите кнопку, относящуюся к ней. После получения ответа или ошибки установите для переменной загрузки значение false, чтобы при нажатии кнопки не запускался повторяющийся запрос.

Обращение с дублирующимися HTTP-вызовами в перехватчиках axios хорошо то, что они, как правило, могут обрабатывать это и предотвращать непредсказуемые результаты, даже если у вас есть настраиваемый контроль состояния загрузки для действий пользователя.

Обратите внимание, что вам все равно придется реализовать это состояние загрузки самостоятельно, если вы хотите улучшить UX для пользователя.

import axios from 'axios'
const service = axios.create({
  baseURL: process.env.BASE_API, // API url
  timeout: 30 * 1000 // API request timeout set to 30s
})
// abort duplicate request
const pending = {}
const CancelToken = axios.CancelToken
const removePending = (config, f) => {
  // make sure the url is same for both request and response
  const url = config.url.replace(config.baseURL, '/')
  // stringify whole RESTful request with URL params
  const flagUrl = url + '&' 
                  + config.method + '&' 
                  + JSON.stringify(config.params)
  if (flagUrl in pending) {
    if (f) {
      f() // abort the request
    } else {
      delete pending[flagUrl]
    }
  } else {
    if (f) {
      pending[flagUrl] = f // store the cancel function
    }
  }
}
// axios interceptors
service.interceptors.request.use(config => {
  // you can apply cancel token to all or specific requests
  // e.g. except config.method == 'options'
  config.cancelToken = new CancelToken((c) => {
    removePending(config, c)
  })
  return config
}, error => {
  Promise.reject(error)
})
service.interceptors.response.use(
  response => {
    removePending(response.config)
    return response.data
  },
  error => {
    removePending(error.config)
    
    if (!axios.isCancel(error)) {
      return Promise.reject(error)
    } else {
      // return empty object for aborted request
      return Promise.resolve({})
    }
  }
)

Прервать ожидающий / предыдущий http-вызов при изменении маршрута

Все вызовы api / запросы ajax для нашего приложения проходят через эту службу, что также дает нам возможность добавлять другие дополнительные функции.

Мы не хотим, чтобы какой-либо ожидающий вызов ajax, сработавший ранее, выполнялся после изменения маршрута. Когда пользователь меняет страницу, все или отдельные предыдущие вызовы Ajax могут быть прерваны, чтобы предотвратить непредвиденные результаты.

Во-первых, добавьте функции прерывания для ожидающего HTTP-вызова в перехватчиках axios.

service.clear = () => {
  Object.keys(pending).map(e => {
    if (pending[e]) {
      pending[e]()
      delete pending[e]
    }
  })
}

Во-вторых, активируйте функцию прерывания в router.beforeEach ()

import router from '@/router'
import request from '@/utils/request' // axios interceptor
router.beforeEach((to, from, next) => {
  request.clear() // clear all pending request
}

Имейте в виду, что при изменении маршрута он просто прервет выполнение слушателей на стороне клиента, процессы на стороне сервера, инициализированные запросом, все равно будут выполняться.