增强你的 axios,分享一个基于 axios 的渐进式请求工具

同学们大家好,忙里偷闲把我在业务中封装的很多请求实用工具分享给大家,为了大家使用方便(也是为了我的开发团队使用方便),我将工具做成了一个库。不占用大家的时间我们直接进入正题,先丢仓库链接,然后介绍这个库是什么东西。 (最近业务压力略大,行文有些潦草,希望大家包涵)

库名: @varlet/axle

github: github.com/varletjs/ax...

设计原则

完全继承 axios 的所有能力,并保留访问 axios 原始对象的能力,不破坏 axios 本身的行为。

介绍

基于 axios 的渐进式请求工具。 它不会破坏 axios 原有的能力,帮助您更轻松地处理请求。

快速开始

安装

shell 复制代码
# 通过 npm, yarn, pnpm 安装

# npm
npm i @varlet/axle -S

#yarn
yarn add @varlet/axle

#pnpm
pnpm add @varlet/axle

发送请求

Axle 归一化了请求函数的参数,并针对不同的业务需求,扩展了更多请求函数,下面是一个简单的例子。

js 复制代码
import { createAxle } from '@varlet/axle'

const axle = createAxle(/** @see https://axios-http.com **/)

axle.get('/url', { current: 1, pageSize: 10 }, { headers: {} })
axle.post('/url', { name: 'Axle' }, { headers: {} })

配置

Axle 完全支持 axios 的所有配置能力。

js 复制代码
const axle = createAxle(/** @see https://axios-http.com **/)
// axle 内置的 axios ,用法和 axios 一模一样,并且和 axle 共享配置。
const { axios } = axle

axios.defaults.baseURL = 'https://api.example.com'
axios.defaults.headers.common['TOKEN'] = TOKEN
axios.defaults.timeout = 2500

// 添加请求前拦截器
axios.interceptors.request.use(
  (config) => {
    // 请求前处理
    return config
  },
  (error) => {
    // 请求错误处理
    return Promise.reject(error)
  }
)

// 添加请求后返回拦截器
axios.interceptors.response.use(
  (response) => {
    // 任何位于 2xx 范围内的状态码都会导致该函数触发
    // 对响应数据做一些事情
    return response
  },
  (error) => {
    // 任何超出 2xx 范围的状态代码都会导致此函数触发
    // 对响应错误做一些事情
    return Promise.reject(error)
  }
)

Axle & Axios 请求函数

Axle 提供的请求函数可以帮助您更轻松地发送请求。 以下是一些示例,包括与 axios 的比较。 提示:下面只是以 getpost 为例,除此之外 Axle 还支持 optionsheaddeletepatchput 方法。

get

JSON

js 复制代码
// axios
axios.get('/url', { params: { id: 1 } })
// axle
axle.get('/url', { id: 1 })

Blob

js 复制代码
// axios
axios.get('/url', { params: { id: 1 }, responseType: 'blob' })
// axle
axle.getBlob('/url', { id: 1 })

Text

js 复制代码
// axios
axios.get('/url', { params: { id: 1 }, responseType: 'text' })
// axle
axle.getText('/url', { id: 1 })

Document

js 复制代码
// axios
axios.get('/url', { params: { id: 1 }, responseType: 'document' })
// axle
axle.getDocument('/url', { id: 1 })

ArrayBuffer

js 复制代码
// axios
axios.get('/url', { params: { id: 1 }, responseType: 'arraybuffer' })
// axle
axle.getArrayBuffer('/url', { id: 1 })

Stream

js 复制代码
// axios
axios.get('/url', { params: { id: 1 }, responseType: 'stream' })
// axle
axle.getStream('/url', { id: 1 })

post

JSON

和 axios 一致。

js 复制代码
// axios
axios.post('/url', { name: 'foo' })
// axle
axle.post('/url', { name: 'foo' })

application/x-www-form-urlencoded

js 复制代码
// axios
axios.post('/url', qs.stringify({ name: 'foo' }), {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
})
// axle
axle.postUrlEncode('/url', { name: 'foo' })

multipart/form-data

js 复制代码
// axios
const formData = new FormData()
formData.append('name', 'foo')
formData.append('file', new File())

axios.post('/url', formData, {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
})
// axle
axle.postMultipart('/url', { name: 'foo', file: new File() })

实用工具

通知浏览器下载文件

js 复制代码
import { download } from '@varlet/axle'

download(await axle.getBlob('/url', { id: 1 }), 'filename')

公共 header 操作

js 复制代码
const headers = axle.getHeaders()
axle.setHeader('TOKEN', TOKEN)
axle.removeHeader('TOKEN')

内置拦截器

Axle 提供了一些实用的请求 / 响应拦截器,并且兼容 axle 和 axios,以下是一些使用案例。同时下方总结了一张所有内置拦截器的表格。

axios

ts 复制代码
import { requestHeadersInterceptor, responseTimeoutInterceptor } from '@varlet/axle'

const headersInterceptor = requestHeadersInterceptor({
  headers: () => ({
    token: localStorage.getItem('token'),
    'Axle-Custom-Header': 'Axle-Custom-Header',
  })
})

const retryInterceptor = responseRetryInterceptor({ count: 3 })

axios.interceptors.request.use(
  headersInterceptor.onFulfilled, 
  headersInterceptor.onRejected, 
  headersInterceptor.options
)
axios.interceptors.response.use(
  retryInterceptor.onFulfilled,
  retryInterceptor.onRejected, 
  retryInterceptor.options
)

axle

ts 复制代码
import { requestHeadersInterceptor, responseTimeoutInterceptor } from '@varlet/axle'

axle.useRequestInterceptor(
  requestHeadersInterceptor({
    headers: () => ({
      token: localStorage.getItem('token'),
      'Axle-Custom-Header': 'Axle-Custom-Header',
    }),
  }),
)

axle.useResponseInterceptor(responseRetryInterceptor({ count: 3 }))

拦截器通用参数 / 拦截器过滤

每个内置拦截器都支持 include exclude axiosInterceptorOptions (与 axios 拦截器一致)

include & exclude

用于请求过滤,以确定什么请求应该应用该拦截器,支持指定 method 或是 glob 语法,使用方式如下。

ts 复制代码
axle.useResponseInterceptor(
  responseRetryInterceptor({ 
    count: 3,
    include: ['method:put', 'method:post'],
    exclude: ['/system/**', '/user/addUser']
  }),
)

内置拦截器一览

名称 描述
requestHeadersInterceptor 用于自定义请求头
requestMockInterceptor 用于模拟数据
responseRetryInterceptor 用于实现请求异常重试
responseStatusInterceptor 用于拦截状态码
responseBlobInterceptor 用于拦截 blob 类型
responseTimeoutInterceptor 用于归一化超时异常

Vue 组合式 API

Axle 提供了 Vue Composition API 风格的用法,封装了请求的 加载状态, 错误状态, 请求的上下行进度返回数据生命周期 等等,并继承了 axios 的所有配置。

html 复制代码
<script setup>
import { createAxle } from '@varlet/axle'
import { createUseAxle } from '@varlet/axle/use'

const axle = createAxle(/** @see https://axios-http.com **/)

const useAxle = createUseAxle({
  axle,
  // 可选项: useAxle 的默认 onTransform
  onTransform: (response) => response,
})

const [users, getUsers, { loading, error, uploadProgress, downloadProgress, abort }] = useAxle({
  // 请求初始化数据
  value: [],
  // 请求方法
  method: 'get',
  // 请求地址
  url: '/user',
  // 是否立即发送请求, 默认值: false
  immediate: true,
  // 请求前是否需要重置 value, 默认值: false
  resetValue: true,
  // 请求参数, 默认值: {}
  // 当参数是一个对象时,发送第一个请求(immediate)时将携带它
  // 当参数是一个函数时,每次发送请求时都会携带它。
  params: { current: 1, pageSize: 10 },
  // Axios 配置, see https://axios-http.com
  config: { headers: {} },
  // 生命周期
  onBefore(refs) {
    const { data, loading, error, uploadProgress, downloadProgress } = refs
    console.log(data.value, loading.value, error.value, uploadProgress.value, downloadProgress.value)
    // 处理请求前逻辑
  },
  onTransform(response, refs) {
    // 处理数据转换,转换后的数据将成为 users 的值。
    return response.data
  },
  onSuccess(response, refs) {
    // 处理请求成功逻辑
  },
  onError(error, refs) {
    // 处理请求错误逻辑
  },
  onAfter(refs) {
    // 处理请求结束逻辑,无论成功失败都会触发。
  },
})
</script>

<template>
  <span>{{ users }}</span>
  <span>{{ loading }}</span>
  <span>{{ error }}</span>
  <span>{{ uploadProgress }}</span>
  <span>{{ downloadProgress }}</span>
  <button @click="getUsers">发送请求</button>
  <button @click="abort">中断请求</button>
</template>

并行请求实用工具

Axle 提供了一些并行请求处理工具,请参考以下示例。

html 复制代码
<script setup>
import { createAxle } from '@varlet/axle'
import { createUseAxle, useValues, useAverageProgress, useHasLoading } from '@varlet/axle/use'

const axle = createAxle(/** @see https://axios-http.com **/)

const useAxle = createUseAxle({ axle })

const [users, getUsers, { loading: isUsersLoading, downloadProgress: usersDownloadProgress }] = useAxle({
  value: [],
  method: 'get',
  url: '/user',
})

const [roles, getRoles, { loading: isRolesLoading, downloadProgress: rolesDownloadProgress }] = useAxle({
  value: [],
  method: 'get',
  url: '/role',
})

// 所有请求结束时,loading 为 false
const loading = useHasLoading(isUsersLoading, isRolesLoading)
// 所有请求结束时,downloadProgress 为 1
const downloadProgress = useAverageProgress(usersDownloadProgress, rolesDownloadProgress)
// Ref<[
//   [{ name: 'foo' }, { name: 'bar' }],
//   [{ role: 'admin' }, { role: 'user' }]
// ]> <-
// [
//   Ref<[{ name: 'foo' }, { name: 'bar' }]>,
//   Ref<[{ role: 'admin' }, { role: 'user' }]>
// ]
const usersRoles = useValues(users, roles)

function sendAllRequest() {
  // parallel
  getUsers()
  getRoles()
}
</script>

<template>
  <span>{{ usersRoles }}</span>
  <span>{{ loading }}</span>
  <span>{{ downloadProgress }}</span>
  <button @click="sendAllRequest">发送全部请求</button>
</template>

结束

希望能对一些同学的工作生活带来便利。

相关推荐
平头哥技术团队1 小时前
Day 16 | 用 ul、ol、li 一个标签,把散资料收成有序的技能清单页
开发语言·前端·html·html5
代码青铜z1 小时前
不会写代码做小程序,模板开发和AI 编程靠谱吗?创业前先看这 5 件事
前端
小傅哥1 小时前
Java + DDD,1:1 复刻 Deepseek Harness 项目
前端·后端·ai编程
积硅步致千里2 小时前
Word 里的 .wmf 其实是 EMF:一次 metafile 转 PNG 排障
前端·后端
mayaairi2 小时前
Vue2 组件通讯(二):ref、自定义事件与provide/inject实战
前端·javascript·vue.js
开开心心就好2 小时前
PDF图片去水印软件,支持批量处理页面
前端·javascript·人工智能·智能手机·pdf·语音识别
爱敲代码的小杨.2 小时前
【Spring】Spring Web MVC
前端·spring·mvc
我的世界洛天依2 小时前
【胡桃讲编程】JS 入门第 1 课:Hello World,开启你的 JavaScript 编程之旅
javascript
是立不是利2 小时前
深入理解JavaScript事件委托
开发语言·前端·javascript
晴天162 小时前
React 版本迭代解析:从15到19 核心差异-Day40
前端·react.js·前端框架