Skip to content

Commit

Permalink
feat: support requestMockInterceptor
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Dec 4, 2023
1 parent 1fbaf7d commit 3138a7f
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ axle.useResponseInterceptor(
| Name | Description |
| --- | --- |
| [requestHeadersInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/requestHeadersInterceptor.ts) | Used to customize the request header |
| [requestMockInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/requestMockInterceptor.ts) | Used to mock data |
| [responseRetryInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/responseRetryInterceptor.ts) | Used to realize the request abnormal retry |
| [responseBlobInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/responseBlobInterceptor.ts) | Used to intercept blob type |
| [responseTimeoutInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/responseTimeoutInterceptor.ts) | Used to abnormal timeout |
Expand Down
1 change: 1 addition & 0 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ axle.useResponseInterceptor(
| 名称 | 描述 |
| --- | --- |
| [requestHeadersInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/requestHeadersInterceptor.ts) | 用于自定义请求头 |
| [requestMockInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/requestMockInterceptor.ts) | 用于模拟数据 |
| [responseRetryInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/responseRetryInterceptor.ts) | 用于实现请求异常重试 |
| [responseBlobInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/responseBlobInterceptor.ts) | 用于拦截 blob 类型 |
| [responseTimeoutInterceptor](https://github.com/varletjs/axle/blob/main/src/interceptors/responseTimeoutInterceptor.ts) | 用于归一化超时异常 |
Expand Down
7 changes: 7 additions & 0 deletions playground/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
usePatchUser,
useDownloadFile,
useThrowError,
useGetMockUsers,
User,
} from './apis'
Expand All @@ -18,6 +19,8 @@ const deleteId = ref('1')
const [users, getUsers, { loading: isUsersLoading }] = useGetUsers<User[]>({ immediate: true })
const [mockUsers, , { loading: isMockUsersLoading }] = useGetMockUsers<User[]>({ immediate: true })
const [user, getUser, { loading: isUserLoading, abort }] = useGetUser({
onSuccess(response) {
if (response.code === 200) {
Expand Down Expand Up @@ -132,6 +135,10 @@ watch(
<var-cell>name: getUsers</var-cell>
<var-cell>loading: {{ isUsersLoading }}</var-cell>
<var-cell>data: {{ users ?? 'No Data' }}</var-cell>

<var-cell>name: getMockUsers</var-cell>
<var-cell>loading: {{ isMockUsersLoading }}</var-cell>
<var-cell>data: {{ mockUsers ?? 'No Data' }}</var-cell>
</var-space>

<var-divider margin="30px 0" />
Expand Down
8 changes: 8 additions & 0 deletions playground/src/apis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ export function useGetUsers<V>(options: Options<V, Response<User[]>>) {
})
}

export function useGetMockUsers<V>(options: Options<V, Response<User[]>>) {
return useAxle({
url: '/mock/list-user',
method: 'get',
...options,
})
}

export function useGetUser<V>(options: Options<V, Response<User>>) {
return useAxle({
url: '/user/get-user',
Expand Down
26 changes: 25 additions & 1 deletion playground/src/request/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
requestHeadersInterceptor,
responseBlobInterceptor,
responseTimeoutInterceptor,
requestMockInterceptor,
} from '@varlet/axle'
import { createUseAxle } from '@varlet/axle/use'

Expand All @@ -21,6 +22,30 @@ axle.useRequestInterceptor(
headers: {
'Axle-Custom-Header': 'Axle-Custom-Header',
},
}),

requestMockInterceptor({
mapping: {
'/mock/**': {
delay: 1000,
handler: () => ({
data: {
code: 200,
data: [
{
id: 1,
name: 'Mock Jack Ma',
},
{
id: 2,
name: 'Mock Tom',
},
],
message: 'success',
},
}),
},
},
})
)

Expand Down Expand Up @@ -52,7 +77,6 @@ axle.useResponseInterceptor(
return response.data
},
onRejected(error) {
console.log(error)
Snackbar.error(error.message)
return Promise.reject(error)
},
Expand Down
1 change: 1 addition & 0 deletions src/interceptors/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './requestHeadersInterceptor'
export * from './requestMockInterceptor'
export * from './responseBlobInterceptor'
export * from './responseTimeoutInterceptor'
export * from './responseRetryInterceptor'
81 changes: 81 additions & 0 deletions src/interceptors/requestMockInterceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { createMatcher } from '../matcher'
import { AxiosError } from 'axios'
import { minimatch } from 'minimatch'
import type { RequestInterceptor } from '../instance'
import type { AxiosInterceptorOptions, AxiosRequestConfig, AxiosResponse } from 'axios'

export type RequestMockInterceptorMappingValue = {
handler: (config: AxiosRequestConfig) => { data: any; status?: number; statusText?: string }
method?: string
delay?: number
}

export interface RequestMockInterceptorOptions {
mapping?: Record<string, RequestMockInterceptorMappingValue>
include?: string[]
exclude?: string[]
axiosInterceptorOptions?: AxiosInterceptorOptions
}

function settle(
response: AxiosResponse,
resolve: (response: AxiosResponse) => void,
reject: (error: AxiosError) => void,
delay = 0
) {
if (delay > 0) {
setTimeout(() => {
settle(response, resolve, reject)
}, delay)
return
}

if (!response.config.validateStatus || response.config.validateStatus(response.status)) {
resolve(response)
} else {
reject(new AxiosError(`Request failed with status code ${response.status}`, undefined, response.config, response))
}
}

export function requestMockInterceptor(options: RequestMockInterceptorOptions = {}): RequestInterceptor {
return {
onFulfilled(config) {
const matcher = createMatcher(options.include, options.exclude)
if (!matcher(config.method ?? '', config.url ?? '')) {
return config
}

const findMappingRecord = () =>
Object.entries(options.mapping ?? {}).find(
([key, value]) => minimatch(config.url ?? '', key) && config.method === (value.method ?? 'get')
)

const mappingRecord = findMappingRecord()
if (!mappingRecord) {
return config
}

const [, mappingValue] = mappingRecord
config.adapter = () => {
const partialResponse = mappingValue.handler(config)
const response: AxiosResponse<any, any> = {
...partialResponse,
headers: config.headers,
config,
request: {},
data: partialResponse.data,
status: partialResponse.status ?? 200,
statusText: partialResponse.statusText ?? 'OK',
}

return new Promise((resolve, reject) => {
settle(response, resolve, reject, mappingValue.delay)
})
}

return config
},
onRejected: (error) => Promise.reject(error),
options: options.axiosInterceptorOptions,
}
}

0 comments on commit 3138a7f

Please sign in to comment.