增强你的 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>

结束

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

相关推荐
m0_748247551 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255022 小时前
前端常用算法集合
前端·算法
真的很上进2 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203982 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2342 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1233 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~4 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语4 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport4 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg4 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全