import { counterActions , counterSelectors } from './slice' ; import { AnyAction , isAllOf , isAnyOf , PayloadAction } from '@reduxjs/toolkit' ; import type { AppListenerApi , AppActionListenerMiddleware } from '../../store' ; function shouldStopAsyncTasksOf ( id ) { return isAllOf ( isAnyOf ( counterActions . cancelAsyncUpdates , counterActions . removeCounter ) , ( action ) : action is PayloadAction < string > => action ?. payload === id ) ; } async function onUpdateByPeriodically ( { payload : { id , delta } , } , { dispatch , getState , getOriginalState , condition } ) { const counter = counterSelectors . selectById ( getState ( ) , id ) ; if ( ! counter || ! counter . intervalMs ) { console . error ( `invalid counter update request` ) ; return ; } const counterBefore = counterSelectors . selectById ( getOriginalState ( ) , id ) ; if ( counterBefore ?. intervalMs ) { console . error ( `counter with id "${ id }" is already updating periodically` ) ; return ; } const intervalRef = setInterval ( ( ) => { dispatch ( counterActions . updateBy ( { id , delta } ) ) ; } , counter . intervalMs ) ; await condition ( shouldStopAsyncTasksOf ( id ) ) ; clearInterval ( intervalRef ) ; console . log ( `stopped periodic update of ${ counter . id }` ) ; } async function onUpdateAsync ( { payload : { id , delta , delayMs } , } , { condition , dispatch , getState } ) { const counter = counterSelectors . selectById ( getState ( ) , id ) ; if ( ! counter ) { console . error ( `could not find counter with id ${ id }` ) ; return ; } if ( ! ( await condition ( shouldStopAsyncTasksOf ( id ) , delayMs ) ) ) { dispatch ( counterActions . updateBy ( { id , delta } ) ) ; } else { console . log ( `blocked async update of ${ counter . id }` ) ; } } example export function setupCounterListeners ( actionListener ) { const subscriptions = [ actionListener . addListener ( { actionCreator : counterActions . updateByPeriodically , listener : onUpdateByPeriodically , } ) , actionListener . addListener ( { actionCreator : counterActions . updateByAsync , listener : onUpdateAsync , } ) , ] ; return ( ) => { subscriptions . forEach ( ( unsubscribe ) => unsubscribe ( ) ) ; } ; }