Не вводите себя в заблуждение, просто прочитайте эту статью, чтобы упаковать Axios

JavaScript axios

Видел в интернете много народных туториалов по упаковке Axios, но есть более-менее неподходящие моменты.Вот рекомендую свои наработки.

Перехватчик не возвращает данные, но все равно возвращает объект AxiosResponse

Все статьи в Интернете позволяют использовать перехватчик для прямого возврата данных, что на самом деле очень неуместно, что затруднит вам расширение последующих функций.

не рекомендуемая практика

import Axios from 'axios'

const client = Axios.create({
  // 你的配置
})

client.interceptors.response.use(response => {
  // 网上的做法都是让你直接返回数据
  // 这导致后续的一些功能难以支持
  return response.data
})

export default client

Рекомендуемая практика

Рекомендуется использовать функции вместо перехватчиков

import Axios, { AxiosRequestConfig } from 'axios'

const client = Axios.create({
  // 你的配置
})

export async function request(url: string, config?: AxiosRequestConfig) {
  const response = await client.request({ url, ...config })
  const result = response.data
  // 你的业务判断逻辑
  return result
}

export default client

Некоторые люди могут сказать, что сейчас это слишком хлопотно, пожалуйста, подождите немного и продолжайте смотреть вниз.

Добавьте расширения к вашему запросу

Часто наш процесс разработки выглядит так:

发送请求 => 拿到数据 => 渲染内容

Но, к сожалению, это только идеальная ситуация, в некоторых особых случаях все равно нужно обрабатывать исключения или дополнительную поддержку, например:

  • Когда запрос терпит неудачу, я надеюсь, что смогу автоматически повторить попытку более 3 раз, прежде чем произойдет сбой.
  • В пейджинговых данных, когда выдается новый запрос, предыдущий запрос автоматически прерывается.
  • Когда третья сторона предоставляет интерфейс jsonp, и вы можете использовать только статические страницы (ps: Axios не поддерживает jsonp)
  • Более

При отправке вышеуказанных сценариев вы можете только писать код для их поддержки в автоматическом режиме, но если вы не перехватываете ответы Axios, вы можете использовать решения, предоставленные сообществом открытого исходного кода.

Повторить запрос в службу поддержки

Установитьaxios-retry, что позволяет вашему Axios поддерживать автоматический повтор

import Axios, { AxiosRequestConfig } from 'axios'
import axiosRetry from 'axios-retry'

const client = Axios.create({
  // 你的配置
})

// 安装 retry 插件
// 当请求失败后,自动重新请求,只有3次失败后才真正失败
axiosRetry(client, { retries: 3 })

export async function request(url: string, config?: AxiosRequestConfig) {
  const response = await client.request({ url, ...config })
  const result = response.data
  // 你的业务判断逻辑
  return result
}

// 只有3次失败后才真正失败
const data = request('http://example.com/test')

PS: плагин axios-retry поддерживает настройку одного запроса

Поддержка jsonp-запроса

Установитьaxios-jsonp, может заставить ваш Axios поддерживать функцию jsonp.

import Axios, { AxiosRequestConfig } from 'axios'
import jsonpAdapter from 'axios-jsonp'

const client = Axios.create({
  // 你的配置
})

export async function request(url: string, config?: AxiosRequestConfig) {
  const response = await client.request({ url, ...config })
  const result = response.data
  // 你的业务判断逻辑
  return result
}

export function jsonp(url: string, config?: AxiosRequestConfig) {
  return request(url, { ...config, adapter: jsonpAdapter })
}

// 你现在可以发送 jsonp 的请求了
const data = jsonp('http://example.com/test-jsonp')

Поддержка версий URI

Любой, у кого есть опыт разработки веб-API, столкнется с проблемой: если в API произошли серьезные изменения, как обеспечить доступность старой версии и выпустить новый API?

Эта ситуация не редкость в сценариях разработки на стороне сервера, особенно для общедоступных API, таких как Douban API (несуществующий).

Текущий мейнстрим поддерживает 3 типа контроля версий:

тип описывать
URI Versioning Версия будет передана в URI запроса (по умолчанию)
Header Versioning Пользовательский заголовок запроса будет указывать версию
Media Type Versioning В заголовке Accept запроса будет указана версия

Версии URIотносится к версии, переданной в URI запроса, например.https://example.com/v1/routeиhttps://example.com/v2/route.

import Axios, { AxiosRequestConfig } from 'axios'

const client = Axios.create({
  // 你的配置
})

client.interceptors.request.use(config => {
  // 最简单的方案
  config.url = config.url.replace('{version}', 'v1')
  return config
})

// GET /api/v1/users
request('/api/{version}/users')

Режим заголовка и типа носителя, вы можете обратиться к следующим статьям, чтобы достичь

сохраняйте уникальные запросы

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

  1. Сначала возвращается запрос на перелистывание страниц, возвращаются данные поиска, а отображение данных нормальное.
  2. Сначала возвращаются данные поиска, возвращаются данные страницы, и данные отображаются неправильно (обычно в сценариях балансировки нагрузки).

С этой целью вы хотите иметь возможность автоматически отменить последний запрос, поэтому вы видели запрос на отмену Axios, но его нужно использовать во многих местах, поэтому вы можете инкапсулировать эту функцию в независимую функцию.

import Axios from 'axios'

const CancelToken = Axios.CancelToken

export function withCancelToken(fetcher) {
  let abort

  function send(data, config) {
    cancel() // 主动取消

    const cancelToken = new CancelToken(cancel => (abort = cancel))
    return fetcher(data, { ...config, cancelToken })
  }

  function cancel(message = 'abort') {
    if (abort) {
      abort(message)
      abort = null
    }
  }

  return [send, cancel]
}

использовать

function getUser(id: string, config?: AxiosRequestConfig) {
  return request(`api/user/${id}`, config)
}

// 包装请求函数
const [fetchUser, abortRequest] = withCancelToken(getUser)

// 发送请求
// 如果上一次请求还没回来,会被自动取消
fetchUser('1000')

// 通常不需要主动调用
// 但可以在组件销毁的生命周期中调用
abortRequest()

Таким образом, когда автоматическая отмена не требуется, исходную функцию можно использовать напрямую, и это не повлияет на использование исходной функции.

послесловие

Инкапсуляция Axios на самом деле имеет много вещей, таких как глобальная обработка ошибок (то же самое не может повлиять на обычные запросы) и т. д. Инкапсуляция не должна просто использовать перехватчики для прямого возврата данных.

Кроме того, модуль запроса должен оставаться независимым, и его рекомендуется расширять.AxiosRequestConfigИли сделать из них независимые функции и предоставить их для внешних вызовов, что удобно сделать независимым HTTP-модулем.