• An async event wrapper that allows multiple calls in an interval to be batched together, and only call the underlying function once.

    Optionally, the output can be unbatched to match the inputs.

    The API is a lot like debounce, but with an additional batch function and an optional unbatch function.

    import { batch } from "@pistonite/pure/sync";

    const execute = batch({
    fn: (n: number) => {
    console.log(n);
    },
    interval: 100,
    // batch receives all the inputs and returns a single input
    // here we just sums the inputs
    batch: (args: [number][]): [number] => [args.reduce((acc, [n]) => acc + n, 0)],
    });

    await execute(1); // logs 1 immediately
    const p1 = execute(2); // will be resolved at 100ms
    const p2 = execute(3); // will be resolved at 100ms
    await Promise.all([p1, p2]); // logs 5 after 100ms

    The optional unbatch function allows the output to be unbatched, so the promises are resolved as if the underlying function is called directly.

    Note that unbatching is usually slow and not required.

    import { batch } from "@pistonite/pure/sync";

    type Message = {
    id: number;
    payload: string;
    }

    const execute = batch({
    fn: (messages: Message[]): Message[] => {
    console.log(messages.length);
    return messages.map((m) => ({
    id: m.id,
    payload: m.payload + "out",
    }));
    },
    batch: (args: [Message[]][]): [Message[]] => {
    const out: Message[] = [];
    for (const [messages] of args) {
    out.push(...messages);
    }
    return [out];
    },
    unbatch: (inputs: [Message[]][], output: Message[]): Message[][] => {
    // not efficient, but just for demonstration
    const idToOutput = new Map();
    for (const o of output) {
    idToOutput.set(o.id, o);
    }
    return inputs.map(([messages]) => {
    return messages.map(({id}) => {
    return idToOutput.get(m.id)!;
    });
    });
    },
    interval: 100,
    });

    const r1 = await execute([{id: 1, payload: "a"}]); // logs 1 immediately
    // r1 is [ {id: 1, payload: "aout"} ]

    const p1 = execute([{id: 2, payload: "b"}]); // will be resolved at 100ms
    const p2 = execute([{id: 3, payload: "c"}]); // will be resolved at 100ms

    const r2 = await p2; // 2 is logged
    // r1 is [ {id: 2, payload: "bout"} ]
    const r3 = await p3; // nothing is logged, as it's already resolved
    // r2 is [ {id: 3, payload: "cout"} ]

    Type Parameters

    • TFn extends (...args: any[]) => any

    Parameters

    Returns (...args: Parameters<TFn>) => Promise<AwaitRet<TFn>>