Skip to content

Commit

Permalink
feat(useAxios): awaitable execute method (#1723)
Browse files Browse the repository at this point in the history
  • Loading branch information
FRSgit committed Jul 6, 2022
1 parent a8fa56c commit 00d7323
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 77 deletions.
8 changes: 8 additions & 0 deletions packages/integrations/useAxios/index.md
Expand Up @@ -62,6 +62,14 @@ const { execute } = useAxios(url1, {}, { immediate: false })
execute(url2)
```

The `execute` function resolves with a result of network request.
```ts
import { useAxios } from '@vueuse/integrations/useAxios'

const { execute } = useAxios()
const result = await execute(url)
```

use an instance of axios with `immediate` options

```ts
Expand Down
101 changes: 50 additions & 51 deletions packages/integrations/useAxios/index.test.ts
Expand Up @@ -12,178 +12,177 @@ describe('useAxios', () => {
})
const options = { immediate: false }
const path = '/todos/1'
test('params: url', (done) => {
test('params: url', async () => {
const { isFinished, data, then } = useAxios(url)
expect(isFinished.value).toBeFalsy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(data.value.id).toBe(1)
expect(result.data).toBe(data)
expect(isFinished.value).toBeTruthy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params: url config', (done) => {
test('params: url config', async () => {
const { isFinished, then } = useAxios(url, config)
expect(isFinished.value).toBeFalsy()
const onRejected = vitest.fn()

then()
await then()
.then((result) => {
expect(result.data.value.id).toBe(1)
expect(isFinished.value).toBeTruthy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params: url config options', (done) => {
test('params: url config options', async () => {
const { isLoading, execute, then } = useAxios(url, config, options)
expect(isLoading.value).toBeFalsy()
execute('https://jsonplaceholder.typicode.com/todos/2')
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

then((result) => {
expect(result.data.value.id).toBe(2)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
const result = await then(undefined, onRejected)
expect(result.data.value.id).toBe(2)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
})

test('params: url instance', (done) => {
test('params: url instance', async () => {
const { isFinished, then } = useAxios(path, instance)
expect(isFinished.value).toBeFalsy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(result.data.value.id).toBe(1)
expect(isFinished.value).toBeTruthy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params: url instance options', (done) => {
test('params: url instance options', async () => {
const { isLoading, execute, then } = useAxios(path, instance, options)
expect(isLoading.value).toBeFalsy()
execute()
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params: url config instance', (done) => {
test('params: url config instance', async () => {
const { isFinished, then } = useAxios(path, config, instance)
expect(isFinished.value).toBeFalsy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(result.data.value.id).toBe(1)
expect(isFinished.value).toBeTruthy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params: url config instance options', (done) => {
test('params: url config instance options', async () => {
const { isLoading, then, execute } = useAxios(path, config, instance, options)
expect(isLoading.value).toBeFalsy()
execute()
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params: url config instance options, execute: config', (done) => {
test('params: url config instance options, execute: config', async () => {
const { isLoading, then, execute } = useAxios(path, config, instance, options)
expect(isLoading.value).toBeFalsy()
execute(undefined, config)
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params no url: nil', (done) => {
const { isLoading, then, execute } = useAxios()
test('params no url: nil', async () => {
const { isLoading, execute } = useAxios()
expect(isLoading.value).toBeFalsy()
execute(url)
const { then } = execute(url)
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params no url: config', (done) => {
const { isLoading, then, execute } = useAxios(config)
test('params no url: config', async () => {
const { isLoading, execute } = useAxios(config)
expect(isLoading.value).toBeFalsy()
execute(url)
const { then } = execute(url)
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

then()
.then((result) => {
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
const result = await then(undefined, onRejected)
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
})

test('params no url: instance', (done) => {
const { isLoading, then, execute } = useAxios(instance)
test('params no url: instance', async () => {
const { isLoading, execute } = useAxios(instance)
expect(isLoading.value).toBeFalsy()
execute(url)
const { then } = execute(path)
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})

test('params no url: config instance', (done) => {
test('params no url: config instance', async () => {
const { isLoading, execute } = useAxios(config, instance)
expect(isLoading.value).toBeFalsy()
const res = execute(path)
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

const result = await res.then(undefined, onRejected)
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
expect(isLoading.value).toBeFalsy()
})

test('execute is awaitable', async () => {
const { isLoading, then, execute } = useAxios(config, instance)
expect(isLoading.value).toBeFalsy()
execute(path)
expect(isLoading.value).toBeTruthy()
const onRejected = vitest.fn()

then((result) => {
await then((result) => {
expect(result.data.value.id).toBe(1)
expect(isLoading.value).toBeFalsy()
expect(onRejected).toBeCalledTimes(0)
done()
}, onRejected)
})
})
44 changes: 18 additions & 26 deletions packages/integrations/useAxios/index.ts
Expand Up @@ -79,13 +79,13 @@ export interface StrictUseAxiosReturn<T> extends UseAxiosReturn<T> {
/**
* Manually call the axios request
*/
execute: (url?: string, config?: AxiosRequestConfig) => void
execute: (url?: string, config?: AxiosRequestConfig) => PromiseLike<StrictUseAxiosReturn<T>>
}
export interface EasyUseAxiosReturn<T> extends UseAxiosReturn<T> {
/**
* Manually call the axios request
*/
execute: (url: string, config?: AxiosRequestConfig) => void
execute: (url: string, config?: AxiosRequestConfig) => PromiseLike<EasyUseAxiosReturn<T>>
}
export interface UseAxiosOptions {
/**
Expand Down Expand Up @@ -160,28 +160,30 @@ export function useAxios<T = any>(...args: any[]): OverallUseAxiosReturn<T> & Pr
isLoading.value = loading
isFinished.value = !loading
}
const waitUntilFinished = () =>
new Promise<OverallUseAxiosReturn<T>>((resolve, reject) => {
until(isFinished).toBe(true)
// eslint-disable-next-line @typescript-eslint/no-use-before-define
.then(() => resolve(result))
.catch(reject)
})
const then: PromiseLike<OverallUseAxiosReturn<T>>['then'] = (onFulfilled, onRejected) =>
waitUntilFinished().then(onFulfilled, onRejected)
const execute: OverallUseAxiosReturn<T>['execute'] = (executeUrl: string | AxiosRequestConfig | undefined = url, config: AxiosRequestConfig = {}) => {
let _url = url ?? ''
let _config
if (typeof executeUrl === 'string') {
_url = executeUrl
_config = config
}
else {
_config = config
}
const _url = typeof executeUrl === 'string'
? executeUrl
: url ?? ''
loading(true)
instance(_url, { ...defaultConfig, ..._config, cancelToken: cancelToken.token })
instance(_url, { ...defaultConfig, ...config, cancelToken: cancelToken.token })
.then((r: any) => {
response.value = r
data.value = r.data
})
.catch((e: any) => {
error.value = e
})
.finally(() => {
loading(false)
})
.finally(() => loading(false))
return { then }
}
if (options.immediate && url)
(execute as StrictUseAxiosReturn<T>['execute'])()
Expand All @@ -202,19 +204,9 @@ export function useAxios<T = any>(...args: any[]): OverallUseAxiosReturn<T> & Pr
abort,
execute,
} as OverallUseAxiosReturn<T>
function waitUntilFinished() {
return new Promise<OverallUseAxiosReturn<T>>((resolve, reject) => {
until(isFinished).toBe(true)
.then(() => resolve(result))
.catch(error => reject(error))
})
}

return {
...result,
then(onFulfilled, onRejected) {
return waitUntilFinished()
.then(onFulfilled, onRejected)
},
then,
}
}

0 comments on commit 00d7323

Please sign in to comment.