diff --git a/packages/integrations/useAxios/index.test.ts b/packages/integrations/useAxios/index.test.ts index f0d37a1a972..c5726906372 100644 --- a/packages/integrations/useAxios/index.test.ts +++ b/packages/integrations/useAxios/index.test.ts @@ -181,9 +181,24 @@ describe('useAxios', () => { await then((result) => { expect(result.data.value.id).toBe(1) - expect(isLoading.value).toBeFalsy() - expect(onRejected).toBeCalledTimes(0) }, onRejected) + expect(isLoading.value).toBeFalsy() + + expect(onRejected).toBeCalledTimes(0) + }) + + test('execute rejects on error', async () => { + const { isLoading, then, execute } = useAxios(config, instance) + expect(isLoading.value).toBeFalsy() + execute(`${path}/wrong-url`) + expect(isLoading.value).toBeTruthy() + const onResolved = vitest.fn() + const onRejected = vitest.fn() + + await then(onResolved, onRejected) + expect(isLoading.value).toBeFalsy() + expect(onResolved).toBeCalledTimes(0) + expect(onRejected).toBeCalledTimes(1) }) test('calling axios with config change(param/data etc.) only', async () => { @@ -262,14 +277,16 @@ describe('useAxios', () => { test('should abort when loading', async () => { const { isLoading, isFinished, isAborted, execute, abort } = useAxios(url, config, options) expect(isLoading.value).toBeFalsy() - execute('https://jsonplaceholder.typicode.com/todos/2').then((result) => { - expect((result.error.value as Error)?.message).toBe('aborted') - expect(isFinished.value).toBeTruthy() - expect(isLoading.value).toBeFalsy() - expect(isAborted.value).toBeTruthy() - }) + let error: any + const promise = execute('https://jsonplaceholder.typicode.com/todos/2') + .catch((e) => { + error = e + }) abort('aborted') + await promise expect(isAborted.value).toBeTruthy() + expect(isFinished.value).toBeTruthy() + expect(error).toBeDefined() }) test('missing url', async () => { @@ -277,8 +294,10 @@ describe('useAxios', () => { console.error = vi.fn() // @ts-expect-error mock undefined url const { execute } = useAxios(undefined, config, options) - const { error } = await execute() - expect(error.value).toBeDefined() + let error: any + await execute() + .catch(e => error = e) + expect(error).toBeDefined() }) test('should call onSuccess when success', async () => { @@ -296,6 +315,7 @@ describe('useAxios', () => { const { execute, error, isLoading, isFinished } = useAxios(url, config, { ...options, onError }) expect(isLoading.value).toBeFalsy() await execute('https://jsonplaceholder.typicode.com/todos/2/3') + .catch(() => {}) expect(onError).toHaveBeenCalledWith(error.value) expect(isFinished.value).toBeTruthy() expect(isLoading.value).toBeFalsy() @@ -321,9 +341,9 @@ describe('useAxios', () => { } const { data, execute } = useAxios(url, config, { ...options, initialData, resetOnExecute: true }) expect(data.value).toEqual(initialData) - await execute() + await execute().catch(() => {}) expect(data.value).toEqual({ completed: false, id: 1, title: 'delectus aut autem', userId: 1 }) - await execute('/todos/312') + await execute('/todos/312').catch(() => {}) expect(data.value).toEqual(initialData) }) @@ -342,9 +362,9 @@ describe('useAxios', () => { } const { data, execute } = useAxios(url, config, { ...options, initialData }) expect(data.value).toEqual(initialData) - await execute() + await execute().catch(() => {}) expect(data.value).toEqual({ completed: false, id: 1, title: 'delectus aut autem', userId: 1 }) - await execute('/todos/312') + await execute('/todos/312').catch(() => {}) expect(data.value).toEqual({ completed: false, id: 1, title: 'delectus aut autem', userId: 1 }) }) diff --git a/packages/integrations/useAxios/index.ts b/packages/integrations/useAxios/index.ts index 3b6aa85f941..5561b06eeae 100644 --- a/packages/integrations/useAxios/index.ts +++ b/packages/integrations/useAxios/index.ts @@ -54,13 +54,13 @@ export interface StrictUseAxiosReturn extends UseAxiosReturn { /** * Manually call the axios request */ - execute: (url?: string | AxiosRequestConfig, config?: AxiosRequestConfig) => PromiseLike> + execute: (url?: string | AxiosRequestConfig, config?: AxiosRequestConfig) => Promise> } export interface EasyUseAxiosReturn extends UseAxiosReturn { /** * Manually call the axios request */ - execute: (url: string, config?: AxiosRequestConfig) => PromiseLike> + execute: (url: string, config?: AxiosRequestConfig) => Promise> } export interface UseAxiosOptions { /** @@ -103,19 +103,19 @@ export interface UseAxiosOptions { } type OverallUseAxiosReturn = StrictUseAxiosReturn | EasyUseAxiosReturn -export function useAxios, D = any>(url: string, config?: AxiosRequestConfig, options?: UseAxiosOptions): StrictUseAxiosReturn & PromiseLike> -export function useAxios, D = any>(url: string, instance?: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn & PromiseLike> -export function useAxios, D = any>(url: string, config: AxiosRequestConfig, instance: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn & PromiseLike> -export function useAxios, D = any>(config?: AxiosRequestConfig): EasyUseAxiosReturn & PromiseLike> -export function useAxios, D = any>(instance?: AxiosInstance): EasyUseAxiosReturn & PromiseLike> -export function useAxios, D = any>(config?: AxiosRequestConfig, instance?: AxiosInstance): EasyUseAxiosReturn & PromiseLike> +export function useAxios, D = any>(url: string, config?: AxiosRequestConfig, options?: UseAxiosOptions): StrictUseAxiosReturn & Promise> +export function useAxios, D = any>(url: string, instance?: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn & Promise> +export function useAxios, D = any>(url: string, config: AxiosRequestConfig, instance: AxiosInstance, options?: UseAxiosOptions): StrictUseAxiosReturn & Promise> +export function useAxios, D = any>(config?: AxiosRequestConfig): EasyUseAxiosReturn & Promise> +export function useAxios, D = any>(instance?: AxiosInstance): EasyUseAxiosReturn & Promise> +export function useAxios, D = any>(config?: AxiosRequestConfig, instance?: AxiosInstance): EasyUseAxiosReturn & Promise> /** * Wrapper for axios. * * @see https://vueuse.org/useAxios */ -export function useAxios, D = any>(...args: any[]): OverallUseAxiosReturn & PromiseLike> { +export function useAxios, D = any>(...args: any[]): OverallUseAxiosReturn & Promise> { const url: string | undefined = typeof args[0] === 'string' ? args[0] : undefined const argsPlaceholder = isString(url) ? 1 : 0 let defaultConfig: AxiosRequestConfig = {} @@ -178,6 +178,7 @@ export function useAxios, D = any>(...args: any[]) isLoading.value = false isFinished.value = false } + const loading = (loading: boolean) => { isLoading.value = loading isFinished.value = !loading @@ -190,15 +191,19 @@ export function useAxios, D = any>(...args: any[]) if (resetOnExecute) data.value = initialData! } + const waitUntilFinished = () => new Promise>((resolve, reject) => { until(isFinished).toBe(true) // eslint-disable-next-line @typescript-eslint/no-use-before-define - .then(() => resolve(result)) - .catch(reject) + .then(() => error.value ? reject(error.value) : resolve(result)) }) - const then: PromiseLike>['then'] = (onFulfilled, onRejected) => - waitUntilFinished().then(onFulfilled, onRejected) + + const promise = { + then: (...args) => waitUntilFinished().then(...args), + catch: (...args) => waitUntilFinished().catch(...args), + } as Promise> + const execute: OverallUseAxiosReturn['execute'] = (executeUrl: string | AxiosRequestConfig | undefined = url, config: AxiosRequestConfig = {}) => { error.value = undefined const _url = typeof executeUrl === 'string' @@ -208,7 +213,7 @@ export function useAxios, D = any>(...args: any[]) if (_url === undefined) { error.value = new AxiosError(AxiosError.ERR_INVALID_URL) isFinished.value = true - return { then } + return promise } resetData() abort() @@ -228,7 +233,7 @@ export function useAxios, D = any>(...args: any[]) options.onFinish?.() loading(false) }) - return { then } + return promise } if (immediate && url) @@ -249,6 +254,6 @@ export function useAxios, D = any>(...args: any[]) return { ...result, - then, + ...promise, } }