after
Creates a function that will invoke the given callback only after it has been called 'count' times.
1/**
2 * Creates a function that will invoke the given callback only
3 * after it has been called 'count' times.
4 *
5 * Includes a .reset() method to restart the call count.
6 *
7 * @param count - Number of calls before the callback is triggered.
8 * @param fn - The function to call after the threshold is reached.
9 * @returns A function with a reset() method.
10 */
11export function after(count: number, fn: () => void): (() => void) & { reset: () => void } {
12 let calls = 0;
13
14 const wrapper = () => {
15 calls++;
16 if (calls >= count) {
17 fn();
18 }
19 };
20
21 wrapper.reset = () => {
22 calls = 0;
23 };
24
25 return wrapper;
26}
Threshold-Based Invocation
Defers execution of a callback until it has been triggered a specified number of times, allowing controlled batching or grouping.
Stateful Execution Logic
Internally tracks call count, eliminating the need for external counters or flags.
Resettable Behavior
Provides a
.reset()
method to restart the internal counter, making it reusable across scenarios or iterations.Simple and Predictable
Minimal implementation with transparent control flow makes it easy to understand and maintain.
Tests | Examples
1test('after - invokes callback only after specified count', () => {
2 const spy = jest.fn();
3 const fn = after(3, spy);
4
5 fn(); // 1
6 fn(); // 2
7 expect(spy).not.toHaveBeenCalled();
8
9 fn(); // 3
10 expect(spy).toHaveBeenCalledTimes(1);
11
12 fn(); // 4
13 fn(); // 5
14 expect(spy).toHaveBeenCalledTimes(3);
15});
16
17test('after - reset() restarts the counter', () => {
18 const spy = jest.fn();
19 const fn = after(2, spy);
20
21 fn(); // 1
22 fn(); // 2 -> trigger
23 expect(spy).toHaveBeenCalledTimes(1);
24
25 fn.reset();
26 fn(); // 1 again
27 fn(); // 2 again -> trigger
28 expect(spy).toHaveBeenCalledTimes(2);
29});
30
31test('after - calls immediately if count is 0 or less', () => {
32 const spy = jest.fn();
33 const fn = after(0, spy);
34
35 fn();
36 expect(spy).toHaveBeenCalledTimes(1);
37
38 fn();
39 expect(spy).toHaveBeenCalledTimes(2);
40});
Common Use Cases
Asynchronous Coordination
Run a final callback only after multiple independent async tasks (e.g., file loads, network calls) have completed.
Testing and Teardown Logic
Wait for multiple assertions or cleanup steps to finish before continuing a test or releasing resources.
UI or Form Completion Checks
Trigger an action after multiple form fields, validation steps, or user interactions are completed.
Batching Event Responses
Fire a response after a defined number of repeated actions (e.g., keyboard input, game mechanics).
Debounced Group Completion
Accumulate a certain number of actions before committing changes, submitting forms, or triggering updates.