diff --git a/packages/@ackee/antonio-utils/README.md b/packages/@ackee/antonio-utils/README.md index 14c23e4..8499b12 100644 --- a/packages/@ackee/antonio-utils/README.md +++ b/packages/@ackee/antonio-utils/README.md @@ -37,7 +37,7 @@ yarn add @ackee/antonio-utils -S #### Parameters -- `actionTypes: Object` +- `actionTypes: TakeRequest` - `REQUEST: ActionPattern` - action type that launches the saga - `CANCEL: ActionPattern` - action type that aborts the running saga - `saga(requestAction, signal: Signal): Function` - the actual API request is made here @@ -65,11 +65,11 @@ export default function* () { #### Parameters -- `params: TakeLatestRequest` - - `REQUEST: ActionPattern` - action type that launches the saga +- `params: TakeLatestRequest` + - `REQUEST: RequestAction['type']` - action type that launches the saga - `cancelTask(requestId: RequestId, action: A): A;` - Redux action that will cancel the running saga - - `requestIdSelector?(action: A): RequestId;` - A function that receives request action as 1st arg. and returns unique ID of this action, e.g. user ID. + - `cancelTask(requestId: RequestId, action: RequestAction): CancelAction;` - A function that receives request action as 1st arg. and returns unique ID of this action, e.g. user ID. - `saga(requestAction, signal: Signal): Function` - the actual API request is made here #### Example diff --git a/packages/@ackee/antonio-utils/src/saga-effects/takeLatestRequest.ts b/packages/@ackee/antonio-utils/src/saga-effects/takeLatestRequest.ts index 081ad31..a65fd8b 100644 --- a/packages/@ackee/antonio-utils/src/saga-effects/takeLatestRequest.ts +++ b/packages/@ackee/antonio-utils/src/saga-effects/takeLatestRequest.ts @@ -1,16 +1,21 @@ +import type { AnyAction } from 'redux'; import { takeEvery, put, spawn } from 'redux-saga/effects'; + import cancellableHandler from './utils/cancellableHandler'; import type { TakeLatestRequest, RequestHandler, RequestId } from '../types'; -export default function* takeLatestRequest( - { REQUEST, cancelTask, requestIdSelector }: TakeLatestRequest, - requestHandler: RequestHandler, +export default function* takeLatestRequest< + RequestAction extends AnyAction = AnyAction, + CancelAction extends AnyAction = AnyAction, +>( + { REQUEST, cancelTask, requestIdSelector }: TakeLatestRequest, + requestHandler: RequestHandler, ) { const runningTasks = new Set(); const DEFAULT_REQUEST_ID = Symbol('DEFAULT_REQUEST_ID'); - yield takeEvery(REQUEST, function* (action) { + yield takeEvery(REQUEST, function* (action: RequestAction) { const requestId = requestIdSelector ? requestIdSelector(action) : DEFAULT_REQUEST_ID; if (runningTasks.has(requestId)) { @@ -18,13 +23,15 @@ export default function* takeLatestRequest( runningTasks.delete(requestId); } - yield spawn(cancellableHandler, { - handler: requestHandler, - handlerArg: action, - CANCEL: cancelTask(requestId, action).type, - onComplete() { - runningTasks.delete(requestId); - }, + yield spawn(function* () { + yield* cancellableHandler({ + handler: requestHandler, + handlerArg: action, + CANCEL: cancelTask(requestId, action).type, + onComplete() { + runningTasks.delete(requestId); + }, + }); }); runningTasks.add(requestId); diff --git a/packages/@ackee/antonio-utils/src/saga-effects/takeRequest.ts b/packages/@ackee/antonio-utils/src/saga-effects/takeRequest.ts index 9cce0b3..7d0d467 100644 --- a/packages/@ackee/antonio-utils/src/saga-effects/takeRequest.ts +++ b/packages/@ackee/antonio-utils/src/saga-effects/takeRequest.ts @@ -1,3 +1,4 @@ +import type { AnyAction } from 'redux'; import { take } from 'redux-saga/effects'; import type { RequestHandler, TakeRequest } from '../types'; import cancellableHandler from './utils/cancellableHandler'; @@ -5,12 +6,15 @@ import cancellableHandler from './utils/cancellableHandler'; /** * Blocking custom saga effect that can cancel the API request */ -export default function* takeRequest(actionTypes: TakeRequest, handler: RequestHandler) { +export default function* takeRequest( + actionTypes: TakeRequest, + handler: RequestHandler, +) { while (true) { /* @ts-ignore */ const action = yield take(actionTypes.REQUEST); - yield cancellableHandler({ + yield cancellableHandler({ handler, handlerArg: action, CANCEL: actionTypes.CANCEL, diff --git a/packages/@ackee/antonio-utils/src/saga-effects/utils/cancellableHandler.ts b/packages/@ackee/antonio-utils/src/saga-effects/utils/cancellableHandler.ts index 413aaea..1777c74 100644 --- a/packages/@ackee/antonio-utils/src/saga-effects/utils/cancellableHandler.ts +++ b/packages/@ackee/antonio-utils/src/saga-effects/utils/cancellableHandler.ts @@ -1,5 +1,7 @@ +import type { AnyAction } from 'redux'; import { call, take, race } from 'redux-saga/effects'; -import { CancellableHandler } from '../../types'; +import type { ActionPattern } from 'redux-saga/effects'; +import type { CancellableHandler } from '../../types'; if (!('AbortController' in window)) { require('abortcontroller-polyfill/dist/abortcontroller-polyfill-only.js'); @@ -7,7 +9,12 @@ if (!('AbortController' in window)) { const noop = function* () {}; -export default function* cancellableHandler({ handlerArg, CANCEL, handler, onComplete = noop }: CancellableHandler) { +export default function* cancellableHandler({ + handlerArg, + CANCEL, + handler, + onComplete = noop, +}: CancellableHandler) { const controller = new AbortController(); function* tasks() { diff --git a/packages/@ackee/antonio-utils/src/types.ts b/packages/@ackee/antonio-utils/src/types.ts index e056f3f..d1dfca5 100644 --- a/packages/@ackee/antonio-utils/src/types.ts +++ b/packages/@ackee/antonio-utils/src/types.ts @@ -1,23 +1,21 @@ -import { AnyAction } from 'redux'; +import type { AnyAction } from 'redux'; import type { ActionPattern } from 'redux-saga/effects'; -type Fn = (...args: any[]) => any; +export type RequestHandler = (requestAction: RequestAction, signal: AbortSignal) => any; -export type RequestHandler = (requestAction: A, signal: AbortSignal) => any; - -export interface CancellableHandler { - handlerArg: any; - CANCEL: ActionPattern; - handler: RequestHandler; - onComplete?: Fn; +export interface CancellableHandler { + handlerArg: RequestAction; + CANCEL: CancelActionType; + handler: RequestHandler; + onComplete?(...args: any[]): void; } export type RequestId = symbol | string | number; -export interface TakeLatestRequest { - REQUEST: ActionPattern; - cancelTask(requestId: RequestId, action: A): A; - requestIdSelector?(action: A): RequestId; +export interface TakeLatestRequest { + REQUEST: RequestAction['type']; + cancelTask(requestId: RequestId, action: RequestAction): CancelAction; + requestIdSelector?(action: RequestAction): RequestId; } export interface TakeRequest {