English | ä¸ć–‡
Progressive request tool based on axios. It does not destroy the original abilities of axios, and helps you process requests more easily.
# Install with npm, yarn or pnpm
# npm
npm i @varlet/axle -S
#yarn
yarn add @varlet/axle
#pnpm
pnpm add @varlet/axleAxle normalizes the parameters of the request function, and expands more request functions for different interface requirements. Here is a simple example.
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 fully supports all configuration abilities of axios.
const axle = createAxle(/** @see https://axios-http.com **/)
// The built-in axios of the axle, the usage is exactly the same as that of axios, and shares the configuration with the axle.
const { axios } = axle
axios.defaults.baseURL = 'https://api.example.com'
axios.defaults.headers.common['TOKEN'] = TOKEN
axios.defaults.timeout = 2500
// Add a request interceptor
axios.interceptors.request.use(
(config) => {
// Do something before request is sent
return config
},
(error) => {
// Do something with request error
return Promise.reject(error)
},
)
// Add a response interceptor
axios.interceptors.response.use(
(response) => {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response
},
(error) => {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error)
},
)The request function provided by Axle can help you send requests more easily. Here are some examples including comparison with axios.
Tips: Take get and post as examples below, Axle also supports options, head, delete, patch , put methods.
// axios
axios.get('/url', { params: { id: 1 } })
// axle
axle.get('/url', { id: 1 })// axios
axios.get('/url', { params: { id: 1 }, responseType: 'blob' })
// axle
axle.getBlob('/url', { id: 1 })// axios
axios.get('/url', { params: { id: 1 }, responseType: 'text' })
// axle
axle.getText('/url', { id: 1 })// axios
axios.get('/url', { params: { id: 1 }, responseType: 'document' })
// axle
axle.getDocument('/url', { id: 1 })// axios
axios.get('/url', { params: { id: 1 }, responseType: 'arraybuffer' })
// axle
axle.getArrayBuffer('/url', { id: 1 })// axios
axios.get('/url', { params: { id: 1 }, responseType: 'stream' })
// axle
axle.getStream('/url', { id: 1 })Same with axios.
// axios
axios.post('/url', { name: 'foo' })
// axle
axle.post('/url', { name: 'foo' })// axios
axios.post('/url', qs.stringify({ name: 'foo' }), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})
// axle
axle.postUrlEncode('/url', { name: 'foo' })// 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() })import { download } from '@varlet/axle'
download(await axle.getBlob('/url', { id: 1 }), 'filename')import { withResponse } from '@varlet/axle'
const { response, errorResponse } = await withResponse(axle.get('/url'))const headers = axle.getHeaders()
axle.setHeader('TOKEN', TOKEN)
axle.removeHeader('TOKEN')axle provides some practical requests/response interceptors, and is compatible with axle and axios.
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)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 }))Each built-in interceptor supports include exclude axiosInterceptorOptions (same with Axios interceptor).
It is used to request filtering to determine what request should apply the interceptor and support specifying the method, status code, pattern function. The usage method is as follows.
axle.useResponseInterceptor(
responseRetryInterceptor({
count: 3,
include: ['method:put', 'method:post', 'status:500'],
exclude: [({ url, method, status }) => url.startsWith('/system'), '/user/addUser', 'status:400'],
}),
)| Name | Description |
|---|---|
| requestHeadersInterceptor | Used to customize the request header |
| requestMockInterceptor | Used to mock data |
| requestMd5Interceptor | Used for md encryption of parameters and headers |
| responseRetryInterceptor | Used to realize the request abnormal retry |
| responseStatusInterceptor | Used to intercept status code |
| responseBlobInterceptor | Used to intercept blob type |
| responseTimeoutInterceptor | Used to abnormal timeout |
Axle provides the usage of Vue Composition API style, which encapsulates the loading status, error status, upload and download progress of the request, return data, lifecycle, etc., And inherit all the configuration of axios.
<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,
// Optional value: Default immediate of the useAxle, defaults true
immediate: false,
// Optional value: Default abortOnUnmount of the useAxle, defaults true
abortOnUnmount: false,
// Optional value: Default onTransform of the useAxle
onTransform: (response) => response,
})
const [
users,
// request runner/invoker
getUsers,
// extra properties
{
loading,
error,
uploadProgress,
downloadProgress,
cancelPolling,
abort,
resetValue,
invalidateCache,
cancelPolling,
},
] = useAxle({
// Request initial value
value: [],
// Request method
method: 'get',
// Request url can be a getter function
url: '/user',
// Whether to send the request immediately, defaults true
immediate: false,
// Whether to abort the request on component unmounted, defaults true
abortOnUnmount: false,
// Whether the value needs to be reset before requesting, defaults false
resetValue: true,
// Automatically reload when reactive inputs change
// When set to true, watch all inputs (params, config, pathParams)
// When set to an object, watch specific inputs:
// - params: true - watch params changes
// - pathParams: true - watch pathParams changes (for API definitions)
// - config: true - watch config changes
watch: true,
// Whether to clone when resetting value, defaults false
// When set to true, use JSON.parse(JSON.stringify(value)) cloned
// When set to a function, the set function will be used as the clone function, such as v => _.cloneDeep(v)
cloneResetValue: true,
// Polling interval, in milliseconds. Passing this configuration enables request polling. The poller will start when the first request is sent.
pollingInterval: 1000,
// Whether to poll when the page is hidden, defaults true
pollingOnHidden: true,
// Whether to poll when the component is deactivated (keep-alive), defaults false
pollingOnDeactivated: false,
// Refresh the request when the window is focused, defaults false
refreshOnWindowFocus: false,
// Request params, defaults {}, can be a getter function
params: { current: 1, pageSize: 10 },
// Axios config, see https://axios-http.com can be a getter function
config: { headers: {} },
// Used to control whether the request can be triggered, returns false will not trigger the request
runnable: () => true,
// lifecycle
onBefore(refs) {
const { data, loading, error, uploadProgress, downloadProgress } = refs
console.log(data.value, loading.value, error.value, uploadProgress.value, downloadProgress.value)
// Do request before
},
onTransform(response, refs) {
// Handle data transform, The transformed data will be the value of users.
return response.data
},
onSuccess(response, refs) {
// Do request success
},
onError(error, refs) {
// Do request error
},
onAfter(refs) {
// Do request after
},
})
</script>
<template>
<span>{{ users }}</span>
<span>{{ loading }}</span>
<span>{{ error }}</span>
<span>{{ uploadProgress }}</span>
<span>{{ downloadProgress }}</span>
<button @click="getUsers">Send Request</button>
<button @click="abort">Abort Request</button>
</template>createApi is supported since v0.9.0, which is used to define APIs.
import { createAxle } from '@varlet/axle'
import { createApi } from '@varlet/axle/api'
import { createUseAxle } from '@varlet/axle/use'
const axle = createAxle({
baseURL: '/api',
})
const useAxle = createUseAxle({
axle,
})
const api = createApi(axle, useAxle)
export const apiGetUsers = api<Response<User[]>>('/user', 'get')
export const apiGetUser = api<Response<User>>('/user/:id', 'get')
export const apiCreateUser = api<Response<User>, CreateUser>('/user', 'post')
export const apiUpdateUser = api<Response<User>, UpdateUser>('/user/:id', 'put')
export const apiDeleteUser = api<Response<User>>('/user/:id', 'delete')
export type Response<T> = {
data: T
code: number
message: string
success: boolean
}
export interface User {
id: string
name: string
}
export interface CreateUser {
name: string
}
export interface UpdateUser {
name: string
}const route = useRoute()
const [users, getUsers] = apiGetUsers.use<Response<User[]>>(/** same as useAxle and extends pathParams **/)
const [user, getUser] = apiGetUser.use<Response<User>>({
pathParams: () => ({ id: route.params.id }),
})
async function handleCreate(params: CreateUser) {
const { success } = await apiCreateUser.load(params)
if (success) {
getUsers()
}
}
async function handleUpdate(params: UpdateUser, id: string) {
const { success } = await apiUpdateUser.load(params, { id })
if (success) {
getUsers()
}
}
async function handleDelete(id: string) {
const { success } = await apiDeleteUser.load({}, { id })
if (success) {
getUsers()
}
}Since v0.10.0, the runner will include all the extra properties, so we can further simplify the work.
before:
<script setup>
const [users, getUsers, { loading: isUsersLoading }] = useAxle({
method: 'get',
url: '/user',
})
const [posts, getPosts, { loading: isPostsLoading }] = useAxle({
method: 'get',
url: '/post',
})
</script>
<template>
<span>{{ isUsersLoading ? 'loading...' : users }}</span>
<span>{{ isPostsLoading ? 'loading...' : posts }}</span>
<button @click="getUsers">Send Request</button>
<button @click="getPosts">Send Request</button>
</template>after:
<script setup>
const [users, getUsers] = useAxle({
method: 'get',
url: '/user',
})
const [posts, getPosts] = useAxle({
method: 'get',
url: '/post',
})
</script>
<template>
<span>{{ getUsers.loading.value ? 'loading...' : users }}</span>
<span>{{ getPosts.loading.value ? 'loading...' : posts }}</span>
<button @click="getUsers">Send Request</button>
<button @click="getPosts">Send Request</button>
</template>The API generation tool can generate all API dispatcher and type declarations through Schema of Openapi3/Swagger2.
We recommend using api-farmer, which has first-party support for axle and is highly customizable.