Skip to content

Commit

Permalink
feat: runner enhancement
Browse files Browse the repository at this point in the history
  • Loading branch information
haoziqaq committed Dec 2, 2024
1 parent 053e95f commit ec1bbab
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 90 deletions.
65 changes: 63 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,14 @@ const useAxle = createUseAxle({
onTransform: (response) => response,
})
const [users, getUsers, { loading, error, uploadProgress, downloadProgress, abort, resetValue }] = useAxle({
const [
// response data
users,
// request runner/invoker
getUsers,
// extra properties
{ loading, error, uploadProgress, downloadProgress, abort, resetValue }
] = useAxle({
// Request initial value
value: [],
// Request method
Expand Down Expand Up @@ -407,7 +414,7 @@ function sendAllRequest() {
</template>
```

### Enhancement
### API Definition Enhancement

`createApi` is supported since `v0.9.0`, which is used to define APIs.

Expand Down Expand Up @@ -494,3 +501,57 @@ async function handleDelete(id: string) {
}
}
```

### Runner Enhancement

Since `v0.10.0`, the `runner` will include all the extra properties, so we can further simplify the work.

before:

```html
<script setup>
const [users, getUsers, { loading: isUsersLoading }] = useAxle({
value: [],
method: 'get',
url: '/user',
})
const [posts, getPosts, { loading: isPostsLoading }] = useAxle({
value: [],
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:

```html
<script setup>
const [users, getUsers] = useAxle({
value: [],
method: 'get',
url: '/user',
})
const [posts, getPosts] = useAxle({
value: [],
method: 'get',
url: '/post',
})
</script>

<template>
<span>{{ getUsers.loading ? 'loading...' : users }}</span>
<span>{{ getPosts.loading ? 'loading...' : posts }}</span>
<button @click="getUsers">Send Request</button>
<button @click="getPosts">Send Request</button>
</template>
```
65 changes: 63 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,14 @@ const useAxle = createUseAxle({
onTransform: (response) => response,
})
const [users, getUsers, { loading, error, uploadProgress, downloadProgress, abort }] = useAxle({
const [
// 请求数据
users,
// 请求触发器
getUsers,
// 附加属性
{ loading, error, uploadProgress, downloadProgress, abort }
] = useAxle({
// 请求初始化数据
value: [],
// 请求方法
Expand Down Expand Up @@ -407,7 +414,7 @@ function sendAllRequest() {
</template>
```

### 增强
### API 定义增强

`0.9.0` 开始支持 `createApi`,以增强 API 定义能力。

Expand Down Expand Up @@ -494,3 +501,57 @@ async function handleDelete(id: string) {
}
}
```

### 请求触发器增强

`v0.10.0` 开始, 请求触发器将包含附加属性中的全部属性。

增强前:

```html
<script setup>
const [users, getUsers, { loading: isUsersLoading }] = useAxle({
value: [],
method: 'get',
url: '/user',
})
const [posts, getPosts, { loading: isPostsLoading }] = useAxle({
value: [],
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>
```

增强后:

```html
<script setup>
const [users, getUsers] = useAxle({
value: [],
method: 'get',
url: '/user',
})
const [posts, getPosts] = useAxle({
value: [],
method: 'get',
url: '/post',
})
</script>

<template>
<span>{{ getUsers.loading ? 'loading...' : users }}</span>
<span>{{ getPosts.loading ? 'loading...' : posts }}</span>
<button @click="getUsers">Send Request</button>
<button @click="getPosts">Send Request</button>
</template>
```
167 changes: 87 additions & 80 deletions packages/axle/src/use.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ export interface RunOptions<V, P> {
cloneResetValue?: boolean | ((value: V) => V)
}

export type Run<V, R, P> = (options?: RunOptions<V, P>) => Promise<R>

export type UseAxleExtra<V> = {
uploadProgress: Ref<number>
downloadProgress: Ref<number>
loading: Ref<boolean>
error: Ref<Error | undefined>
abort(): void
resetValue(options?: ResetValueOptions<V>): void
}
export interface UseAxleRefs<V> {
value: Ref<V>
loading: Ref<boolean>
Expand All @@ -20,6 +26,10 @@ export interface UseAxleRefs<V> {
downloadProgress: Ref<number>
}

export type Run<V, R, P> = {
(options?: RunOptions<V, P>): Promise<R>
} & UseAxleExtra<V>

export interface UseAxleOptions<V = any, R = any, P = Record<string, any>> {
url: string | (() => string)
method: RunnerMethod
Expand All @@ -40,18 +50,7 @@ export interface ResetValueOptions<V> {
cloneResetValue?: boolean | ((value: V) => V)
}

export type UseAxleInstance<V, R, P> = [
value: Ref<V>,
run: Run<V, R, P>,
extra: {
uploadProgress: Ref<number>
downloadProgress: Ref<number>
loading: Ref<boolean>
error: Ref<Error | undefined>
abort(): void
resetValue(options?: ResetValueOptions<V>): void
}
]
export type UseAxleInstance<V, R, P> = [value: Ref<V>, run: Run<V, R, P>, extra: UseAxleExtra<V>]

export interface CreateUseAxleOptions {
axle: AxleInstance
Expand Down Expand Up @@ -104,75 +103,79 @@ export function createUseAxle(options: CreateUseAxleOptions) {
uploadProgress,
}

let controller = new AbortController()

const resetValue = (options: ResetValueOptions<V> = {}) => {
const cloneResetValue = options.cloneResetValue ?? initialCloneResetValue ?? false
const cloneFn =
cloneResetValue === true
? (v: V) => (v == null ? null : JSON.parse(JSON.stringify(v)))
: isFunction(initialCloneResetValue)
? initialCloneResetValue
: (v: V) => v
value.value = cloneFn(initialValue as V)
const extra: UseAxleExtra<V> = {
uploadProgress,
downloadProgress,
loading,
error,
abort,
resetValue,
}

const run: Run<V, R, P> = async (options: RunOptions<V, P> = {}) => {
if (controller.signal.aborted) {
controller = new AbortController()
}
let controller = new AbortController()

const resetValueOption = options.resetValue ?? initialResetValue ?? false
if (resetValueOption === true) {
resetValue(options)
}
const run: Run<V, R, P> = Object.assign(
async (options: RunOptions<V, P> = {}) => {
if (controller.signal.aborted) {
controller = new AbortController()
}

uploadProgress.value = 0
downloadProgress.value = 0
const resetValueOption = options.resetValue ?? initialResetValue ?? false
if (resetValueOption === true) {
resetValue(options)
}

const url = options.url ?? normalizeValueGetter(initialUrlOrGetter)
const params = options.params ?? normalizeValueGetter(initialParamsOrGetter)
const config = options.config ?? normalizeValueGetter(initialConfigOrGetter)
uploadProgress.value = 0
downloadProgress.value = 0

onBefore(refs)
const url = options.url ?? normalizeValueGetter(initialUrlOrGetter)
const params = options.params ?? normalizeValueGetter(initialParamsOrGetter)
const config = options.config ?? normalizeValueGetter(initialConfigOrGetter)

loading.value = true
onBefore(refs)

try {
const response = await axle[method](url, params, {
signal: controller.signal,
loading.value = true

onUploadProgress(event) {
uploadProgress.value = event.progress ?? 0
},
try {
const response = await axle[method](url, params, {
signal: controller.signal,

onDownloadProgress(event) {
downloadProgress.value = event.progress ?? 0
},
onUploadProgress(event) {
uploadProgress.value = event.progress ?? 0
},

...config,
})
onDownloadProgress(event) {
downloadProgress.value = event.progress ?? 0
},

value.value = await onTransform(response as R, refs)
error.value = undefined
onSuccess(response as R, refs)
loading.value = false
onAfter(refs)
...config,
})

return response as R
} catch (responseError: any) {
error.value = responseError as Error
onError(responseError as Error, refs)
loading.value = false
onAfter(refs)
value.value = await onTransform(response as R, refs)
error.value = undefined
onSuccess(response as R, refs)
loading.value = false
onAfter(refs)

throw responseError
}
}
return response as R
} catch (responseError: any) {
error.value = responseError as Error
onError(responseError as Error, refs)
loading.value = false
onAfter(refs)

const abort = () => {
controller.abort()
}
throw responseError
}
},
{
uploadProgress,
downloadProgress,
loading,
error,
abort,
resetValue,
}
)

if (immediate) {
run({
Expand All @@ -182,18 +185,22 @@ export function createUseAxle(options: CreateUseAxleOptions) {
})
}

return [
value,
run,
{
loading,
error,
uploadProgress,
downloadProgress,
abort,
resetValue,
},
]
function resetValue(options: ResetValueOptions<V> = {}) {
const cloneResetValue = options.cloneResetValue ?? initialCloneResetValue ?? false
const cloneFn =
cloneResetValue === true
? (v: V) => (v == null ? null : JSON.parse(JSON.stringify(v)))
: isFunction(initialCloneResetValue)
? initialCloneResetValue
: (v: V) => v
value.value = cloneFn(initialValue as V)
}

function abort() {
controller.abort()
}

return [value, run, extra]
}

return useAxle
Expand Down
Loading

0 comments on commit ec1bbab

Please sign in to comment.