From 479e5258fa15230b0c7c0284862c1f83e063c94f Mon Sep 17 00:00:00 2001 From: Jakub Freisler Date: Tue, 28 Jun 2022 01:06:28 +0200 Subject: [PATCH] feat(useAxios): awaitable execute method simplify execute var definitions migrate to async methods to silent vitest warnings BREAKING CHANGE: change return type of useAxios.execute method to PromiseLike result Signed-off-by: Jakub Freisler --- packages/contributors.json | 3 + packages/integrations/useAxios/index.md | 8 ++ packages/integrations/useAxios/index.test.ts | 101 +++++++++---------- packages/integrations/useAxios/index.ts | 44 ++++---- 4 files changed, 79 insertions(+), 77 deletions(-) diff --git a/packages/contributors.json b/packages/contributors.json index 238831518ee..0472f66a85c 100644 --- a/packages/contributors.json +++ b/packages/contributors.json @@ -166,6 +166,7 @@ "phaust", "marktnoonan", "dm4t2", + "melishev", "mauriciabad", "mxmvshnvsk", "AldeonMoriak", @@ -223,10 +224,12 @@ "monkeywithacupcake", "katsuyaU", "koheing", + "kongmoumou", "laozei6401", "leovoon", "likeswinds", "lxhyl", + "lxnelyclxud", "lzdFeiFei", "meteorlxy", "odex21", diff --git a/packages/integrations/useAxios/index.md b/packages/integrations/useAxios/index.md index fbfa6c5db19..8226c635d3d 100644 --- a/packages/integrations/useAxios/index.md +++ b/packages/integrations/useAxios/index.md @@ -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 diff --git a/packages/integrations/useAxios/index.test.ts b/packages/integrations/useAxios/index.test.ts index da8161dc02f..46749623873 100644 --- a/packages/integrations/useAxios/index.test.ts +++ b/packages/integrations/useAxios/index.test.ts @@ -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) }) }) diff --git a/packages/integrations/useAxios/index.ts b/packages/integrations/useAxios/index.ts index 1df15281830..8cdbf17e57c 100644 --- a/packages/integrations/useAxios/index.ts +++ b/packages/integrations/useAxios/index.ts @@ -79,13 +79,13 @@ export interface StrictUseAxiosReturn extends UseAxiosReturn { /** * Manually call the axios request */ - execute: (url?: string, config?: AxiosRequestConfig) => void + execute: (url?: string, config?: AxiosRequestConfig) => PromiseLike> } export interface EasyUseAxiosReturn extends UseAxiosReturn { /** * Manually call the axios request */ - execute: (url: string, config?: AxiosRequestConfig) => void + execute: (url: string, config?: AxiosRequestConfig) => PromiseLike> } export interface UseAxiosOptions { /** @@ -160,18 +160,21 @@ export function useAxios(...args: any[]): OverallUseAxiosReturn & Pr isLoading.value = loading isFinished.value = !loading } + 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) + }) + const then: PromiseLike>['then'] = (onFulfilled, onRejected) => + waitUntilFinished().then(onFulfilled, onRejected) const execute: OverallUseAxiosReturn['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 @@ -179,9 +182,8 @@ export function useAxios(...args: any[]): OverallUseAxiosReturn & Pr .catch((e: any) => { error.value = e }) - .finally(() => { - loading(false) - }) + .finally(() => loading(false)) + return { then } } if (options.immediate && url) (execute as StrictUseAxiosReturn['execute'])() @@ -202,19 +204,9 @@ export function useAxios(...args: any[]): OverallUseAxiosReturn & Pr abort, execute, } as OverallUseAxiosReturn - function waitUntilFinished() { - return new Promise>((resolve, reject) => { - until(isFinished).toBe(true) - .then(() => resolve(result)) - .catch(error => reject(error)) - }) - } return { ...result, - then(onFulfilled, onRejected) { - return waitUntilFinished() - .then(onFulfilled, onRejected) - }, + then, } }