Skip to content

Commit

Permalink
Merge pull request #453 from alovajs/fix/sqrequest
Browse files Browse the repository at this point in the history
fix: cannot stop pushing SilentMethod into queue when using async handler in onBeforePushQueue(#434)
  • Loading branch information
MeetinaXD authored Jul 12, 2024
2 parents cafee1e + a5c6dd3 commit b469662
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 38 deletions.
5 changes: 5 additions & 0 deletions .changeset/angry-laws-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'alova': patch
---

fix: cannot stop pushing SilentMethod into queue when using async handler in onBeforePushQueue(#434)
70 changes: 47 additions & 23 deletions packages/alova/typings/clienthook/hooks/tokenAuthentication.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import { AlovaGenerics, AlovaOptions, AlovaRequestAdapter, Method, StatesHook } from 'alova';
import adapterFetch from 'alova/fetch';

/**
* 统一获取AlovaRequestAdapter的类型
*/
export type AlovaRequestAdapterUnified<
RA extends
| AlovaRequestAdapter<any, any, any>
| ((...args: any[]) => AlovaRequestAdapter<any, any, any>) = AlovaRequestAdapter<any, any, any>
> = RA extends AlovaRequestAdapter<any, any, any> ? RA : ReturnType<RA>;

// transform types StateHook and AlovaRequestAdapter to an AlovaGenerics
export type StateHookAdapter2AG<SH extends StatesHook<any>, RA extends AlovaRequestAdapter<any, any, any>> =
Parameters<RA>[1] extends Method<AlovaGenerics<infer R, infer T, infer RC, infer RE, infer RH>>
? AlovaGenerics<R, T, RC, RE, RH, any, any, SH extends StatesHook[''] ? SE : unknown>
: never;

export type AlovaResponded<SH extends StatesHook<any>, RA extends AlovaRequestAdapter<any, any, any>> = NonNullable<
AlovaOptions<
Omit<AlovaGenerics, 'StatesExport'> & {
StatesExport: SH extends StatesHook<infer SE> ? SE : any;
} & (Parameters<RA>[1] extends Method<infer AG> ? AG : never)
>['responded']
AlovaOptions<StateHookAdapter2AG<SH, RA>>['responded']
>;

export type MetaMatches = Record<string, any>;
Expand Down Expand Up @@ -69,18 +81,22 @@ export interface ClientTokenAuthenticationOptions<RA extends AlovaRequestAdapter
};
}

export type BeforeRequestType<AG extends AlovaGenerics> = (
originalBeforeRequest?: AlovaOptions<AG>['beforeRequest']
) => AlovaOptions<AG>['beforeRequest'];
export type ResponseType<AG extends AlovaGenerics> = (
originalResponded?: AlovaOptions<AG>['responded']
) => AlovaOptions<AG>['responded'];
export type AlovaBeforeRequest<SH extends StatesHook<any>, RA extends AlovaRequestAdapter<any, any, any>> = (
method: Method<StateHookAdapter2AG<SH, RA>>
) => void | Promise<void>;

type BeforeRequestType<SH extends StatesHook<any>, RA extends AlovaRequestAdapter<any, any, any>> = (
originalBeforeRequest?: AlovaBeforeRequest<SH, RA>
) => AlovaBeforeRequest<SH, RA>;
type ResponseType<SH extends StatesHook<any>, RA extends AlovaRequestAdapter<any, any, any>> = (
originalResponded?: AlovaResponded<SH, RA>
) => AlovaResponded<SH, RA>;

export interface TokenAuthenticationResult<AG extends AlovaGenerics> {
onAuthRequired: BeforeRequestType<AG>;
onResponseRefreshToken: ResponseType<AG>;
export interface TokenAuthenticationResult<SH extends StatesHook<any>, RA extends AlovaRequestAdapter<any, any, any>> {
onAuthRequired: BeforeRequestType<SH, RA>;
onResponseRefreshToken: ResponseType<SH, RA>;
waitingList: {
method: Method;
method: Method<StateHookAdapter2AG<SH, RA>>;
resolve: () => void;
}[];
}
Expand Down Expand Up @@ -147,11 +163,14 @@ export interface ServerTokenAuthenticationOptions<RA extends AlovaRequestAdapter
* @param options 配置参数
* @returns token认证拦截器函数
*/
export declare function createClientTokenAuthentication<AG extends AlovaGenerics = AlovaGenerics>(
options: ClientTokenAuthenticationOptions<
AlovaRequestAdapter<AG['RequestConfig'], AG['Response'], AG['ResponseHeader']>
>
): TokenAuthenticationResult<AG>;
export declare function createClientTokenAuthentication<
SH extends StatesHook<any>,
RA extends
| AlovaRequestAdapter<any, any, any>
| ((...args: any[]) => AlovaRequestAdapter<any, any, any>) = typeof adapterFetch
>(
options: ClientTokenAuthenticationOptions<AlovaRequestAdapterUnified<RA>>
): TokenAuthenticationResult<SH, AlovaRequestAdapterUnified<RA>>;

/**
* 创建服务端的token认证拦截器
Expand All @@ -176,6 +195,11 @@ export declare function createClientTokenAuthentication<AG extends AlovaGenerics
* @param options 配置参数
* @returns token认证拦截器函数
*/
export declare function createServerTokenAuthentication<AG extends AlovaGenerics = AlovaGenerics>(
options: ServerTokenAuthenticationOptions<AlovaRequestAdapter<any, any, any>>
): TokenAuthenticationResult<AG>;
export declare function createServerTokenAuthentication<
SH extends StatesHook<any>,
RA extends
| AlovaRequestAdapter<any, any, any>
| ((...args: any[]) => AlovaRequestAdapter<any, any, any>) = typeof adapterFetch
>(
options: ServerTokenAuthenticationOptions<AlovaRequestAdapterUnified<RA>>
): TokenAuthenticationResult<SH, AlovaRequestAdapterUnified<RA>>;
23 changes: 16 additions & 7 deletions packages/alova/typings/clienthook/hooks/useFetcher.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import { Alova, AlovaGenerics, FetchRequestState, Method, Progress, ReferingObject, StatesHook } from 'alova';
import {
Alova,
AlovaGenerics,
FetchRequestState,
Method,
Progress,
ReferingObject,
StatesExport,
StatesHook
} from 'alova';
import {
AlovaFetcherMiddleware,
ExportedState,
Expand All @@ -24,14 +33,14 @@ export interface FetcherHookConfig<AG extends AlovaGenerics = AlovaGenerics> ext
updateState?: boolean;
}

export interface UseFetchExportedState<State>
export interface UseFetchExportedState<SE extends StatesExport>
extends FetchRequestState<
ExportedState<boolean, State>,
ExportedState<Error | undefined, State>,
ExportedState<Progress, State>,
ExportedState<Progress, State>
ExportedState<boolean, SE>,
ExportedState<Error | undefined, SE>,
ExportedState<Progress, SE>,
ExportedState<Progress, SE>
> {}
export interface UseFetchHookExposure<SE extends StatesExport> extends UseFetchExportedState<SE['State']> {
export interface UseFetchHookExposure<SE extends StatesExport> extends UseFetchExportedState<SE> {
fetch<R>(matcher: Method<AlovaGenerics<R>>, ...args: any[]): Promise<R>;
update: StateUpdater<UseFetchExportedState<SE['State']>, SE>;
abort: UseHookExposure['abort'];
Expand Down
4 changes: 3 additions & 1 deletion packages/alova/typings/clienthook/hooks/useSQRequest.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,9 @@ export interface SQHookConfig<AG extends AlovaGenerics> {
export type SQRequestHookConfig<AG extends AlovaGenerics> = SQHookConfig<AG> & RequestHookConfig<AG>;
export type FallbackHandler<AG extends AlovaGenerics> = (event: ScopedSQEvent<AG>) => void;
export type RetryHandler<AG extends AlovaGenerics> = (event: ScopedSQRetryEvent<AG>) => void;
export type BeforePushQueueHandler<AG extends AlovaGenerics> = (event: ScopedSQEvent<AG>) => void | boolean;
export type BeforePushQueueHandler<AG extends AlovaGenerics> = (
event: ScopedSQEvent<AG>
) => void | boolean | Promise<void | boolean>;
export type PushedQueueHandler<AG extends AlovaGenerics> = (event: ScopedSQEvent<AG>) => void;
export type SQHookExposure<AG extends AlovaGenerics> = Omit<
UseHookExposure<AG>,
Expand Down
5 changes: 3 additions & 2 deletions packages/client/src/hooks/silent/silentQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,14 @@ export const pushNewSilentMethod2Queue = async <AG extends AlovaGenerics>(
silentMethodInstance: SilentMethod<AG>,
cache: boolean,
targetQueueName = DEFAULT_QUEUE_NAME,
onBeforePush: () => any[] = () => []
onBeforePush: () => any[] | Promise<any>[] = () => []
) => {
silentMethodInstance.cache = cache;
const currentQueue = (silentQueueMap[targetQueueName] =
silentQueueMap[targetQueueName] || []) as unknown as SilentMethod<AG>[];
const isNewQueue = len(currentQueue) <= 0;
const isPush2Queue = !onBeforePush().some(returns => returns === falseValue);
const beforePushReturns = await Promise.all(onBeforePush());
const isPush2Queue = !beforePushReturns.some(returns => returns === falseValue);

// silent行为下,如果没有绑定fallback事件回调,则持久化
// 如果在onBeforePushQueue返回false,也不再放入队列中
Expand Down
12 changes: 8 additions & 4 deletions packages/client/test/vue/useSQRequest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,19 @@ describe('vue => useSQRequest', () => {

test('should prevent to push silentMethod when return false in certain callback of onBeforePushQueue', async () => {
const queue = 'tb4';
const successMockFn = jest.fn();
const Get = () => alovaInst.Get<any>('/list');
const { onBeforePushQueue, onSuccess } = useSQRequest(Get, {
const { onBeforePushQueue } = useSQRequest(Get, {
behavior: 'queue',
queue
});
}).onSuccess(successMockFn);
const { onBeforePushQueue: onBeforePushQueueAsync } = useSQRequest(Get, {
behavior: 'queue',
queue
}).onSuccess(successMockFn);
onBeforePushQueue(() => false);
onBeforePushQueueAsync(() => Promise.resolve(false));

const successMockFn = jest.fn();
onSuccess(successMockFn);
await delay(0);
expect(silentQueueMap[queue]).toStrictEqual([]);
await delay(500);
Expand Down
4 changes: 3 additions & 1 deletion packages/client/typings/clienthook/hooks/useSQRequest.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,9 @@ export interface SQHookConfig<AG extends AlovaGenerics> {
export type SQRequestHookConfig<AG extends AlovaGenerics> = SQHookConfig<AG> & RequestHookConfig<AG>;
export type FallbackHandler<AG extends AlovaGenerics> = (event: ScopedSQEvent<AG>) => void;
export type RetryHandler<AG extends AlovaGenerics> = (event: ScopedSQRetryEvent<AG>) => void;
export type BeforePushQueueHandler<AG extends AlovaGenerics> = (event: ScopedSQEvent<AG>) => void | boolean;
export type BeforePushQueueHandler<AG extends AlovaGenerics> = (
event: ScopedSQEvent<AG>
) => void | boolean | Promise<void | boolean>;
export type PushedQueueHandler<AG extends AlovaGenerics> = (event: ScopedSQEvent<AG>) => void;
export type SQHookExposure<AG extends AlovaGenerics> = Omit<
UseHookExposure<AG>,
Expand Down

0 comments on commit b469662

Please sign in to comment.