From 5b1c001a522d9c8fa69d16516100fb025ad3b8c1 Mon Sep 17 00:00:00 2001 From: liaochunxin Date: Tue, 23 Sep 2025 11:09:55 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix(http):=20=E9=BB=98=E8=AE=A4=E5=80=BC?= =?UTF-8?q?=E5=A4=84=E7=90=86=EF=BC=8C=E7=A1=AE=E4=BF=9D=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=E6=88=90=E5=8A=9F=E5=9B=A0=E4=B8=BA=E8=A7=A3=E6=9E=84=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E5=BC=82=E5=B8=B8=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/http/http.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http/http.ts b/src/http/http.ts index 953bdbd..54e4a66 100644 --- a/src/http/http.ts +++ b/src/http/http.ts @@ -24,7 +24,7 @@ export function http(options: CustomRequestOptions) { // 状态码 2xx,参考 axios 的设计 if (res.statusCode >= 200 && res.statusCode < 300) { // 2.1 处理业务逻辑错误 - const { code, message, data } = res.data as IResponse + const { code = 0, message = '', data = null } = res.data as IResponse // 0和200当做成功都很普遍,这里直接兼容两者,见 ResultEnum if (code !== ResultEnum.Success0 && code !== ResultEnum.Success200) { throw new Error(`请求错误[${code}]:${message}`) From bc6dcdde93da18c7975fba7f8b235ce50837cdec Mon Sep 17 00:00:00 2001 From: liaochunxin Date: Tue, 23 Sep 2025 15:36:33 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix(api):=20=E4=BF=AE=E6=94=B9=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E6=94=AF=E6=8C=81=E5=BC=82=E6=AD=A5=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E5=92=8C=E6=99=AE=E9=80=9A=E5=87=BD=E6=95=B0=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=BF=94=E5=9B=9EPromise=EF=BC=8C=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/foo.ts | 4 ++-- src/hooks/useRequest.ts | 32 ++++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/api/foo.ts b/src/api/foo.ts index cfa39a5..a500002 100644 --- a/src/api/foo.ts +++ b/src/api/foo.ts @@ -21,8 +21,8 @@ export interface IFooItem { } /** GET 请求 */ -export function getFooAPI(name: string) { - return http.get('/foo', { name }) +export async function getFooAPI(name: string) { + return await http.get('/foo', { name }) } /** GET 请求;支持 传递 header 的范例 */ export function getFooAPI2(name: string) { diff --git a/src/hooks/useRequest.ts b/src/hooks/useRequest.ts index 7aa7bc6..7eae39e 100644 --- a/src/hooks/useRequest.ts +++ b/src/hooks/useRequest.ts @@ -26,7 +26,7 @@ interface IUseRequestReturn { * @returns 返回一个对象{loading, error, data, run},包含请求的加载状态、错误信息、响应数据和手动触发请求的函数。 */ export default function useRequest( - func: (args?: P) => HttpRequestResult, + func: (args?: P) => Promise | Promise> | HttpRequestResult | T, options: IUseRequestOptions = { immediate: false }, ): IUseRequestReturn { const loading = ref(false) @@ -36,12 +36,36 @@ export default function useRequest( const run = async (args?: P) => { loading.value = true - const { promise, requestTask: task } = func(args) - requestTask = task // Store the requestTask + error.value = false // Move error reset to the beginning + let promise: Promise + const result = func(args) + + if (result instanceof Promise) { + // If func returns a Promise + promise = result.then((res) => { + if (res && typeof (res as HttpRequestResult).promise === 'object' && typeof (res as HttpRequestResult).requestTask === 'object') { + // If the resolved value is HttpRequestResult + const { promise: p, requestTask: task } = res as HttpRequestResult + requestTask = task + return p + } + return res as T | undefined + }) as Promise // Cast to ensure correct type + } + else if (result && typeof (result as HttpRequestResult).promise === 'object' && typeof (result as HttpRequestResult).requestTask === 'object') { + // If func returns HttpRequestResult directly + const { promise: p, requestTask: task } = result as HttpRequestResult + requestTask = task + promise = p + } + else { + // If func returns T directly + promise = Promise.resolve(result as T | undefined) + } + return promise .then((res) => { data.value = res - error.value = false return data.value }) .catch((err) => { From a8ec7f7beb03a9bf875ed5a9ca6ed984a076b5da Mon Sep 17 00:00:00 2001 From: liaochunxin Date: Tue, 23 Sep 2025 15:53:38 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix(useRequest):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=8F=96=E6=B6=88=E8=AF=B7=E6=B1=82=E6=97=B6=E6=9C=AA=E6=8D=95?= =?UTF-8?q?=E8=8E=B7=E7=9A=84=20Promise=20=E9=94=99=E8=AF=AF=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E4=B8=94=E7=BD=91=E7=BB=9C=E8=AF=B7=E6=B1=82=E6=9C=AC?= =?UTF-8?q?=E8=BA=AB=E4=B9=9F=E4=BC=9A=E8=A2=AB=E4=B8=AD=E6=AD=A2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useRequest.ts | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/hooks/useRequest.ts b/src/hooks/useRequest.ts index 7eae39e..1290dbd 100644 --- a/src/hooks/useRequest.ts +++ b/src/hooks/useRequest.ts @@ -33,44 +33,55 @@ export default function useRequest( const error = ref(false) const data = ref(options.initialData) as Ref let requestTask: UniApp.RequestTask | undefined + const isCancelled = ref(false) - const run = async (args?: P) => { + const run = async (args?: P): Promise => { loading.value = true - error.value = false // Move error reset to the beginning + error.value = false + isCancelled.value = false let promise: Promise const result = func(args) if (result instanceof Promise) { - // If func returns a Promise promise = result.then((res) => { if (res && typeof (res as HttpRequestResult).promise === 'object' && typeof (res as HttpRequestResult).requestTask === 'object') { - // If the resolved value is HttpRequestResult const { promise: p, requestTask: task } = res as HttpRequestResult requestTask = task + if (isCancelled.value) { + task.abort() + throw new Error('Request cancelled') + } return p } + if (isCancelled.value) { + throw new Error('Request cancelled') + } return res as T | undefined - }) as Promise // Cast to ensure correct type + }) as Promise } else if (result && typeof (result as HttpRequestResult).promise === 'object' && typeof (result as HttpRequestResult).requestTask === 'object') { - // If func returns HttpRequestResult directly const { promise: p, requestTask: task } = result as HttpRequestResult requestTask = task promise = p } else { - // If func returns T directly promise = Promise.resolve(result as T | undefined) } return promise .then((res) => { + if (isCancelled.value) { + return + } data.value = res return data.value }) .catch((err) => { - error.value = err - throw err + if (!isCancelled.value) { + error.value = err + throw err + } + return Promise.resolve(undefined) }) .finally(() => { loading.value = false @@ -78,11 +89,12 @@ export default function useRequest( } const cancel = () => { + isCancelled.value = true if (requestTask) { requestTask.abort() - loading.value = false // Reset loading state on cancel - error.value = new Error('Request cancelled') // Set a specific error for cancellation } + loading.value = false + error.value = new Error('Request cancelled') } if (options.immediate) {