Overview
asyncAction takes an async function and returns an enhanced callable that automatically manages a reactive state machine. Instead of manually setting isLoading, error, and data atoms around every await, you get them as reactive atoms you can read directly in templates.
The returned object is directly callable — fetchUser('u_1'). Reactive atoms update automatically: isLoading flips to true when the call starts, and status transitions through 'loading' → 'success' (or 'error') when it settles.
asyncAction vs asyncAtom vs fetchAction
|
API
|
Invocation
|
Prefer when
|
|---|---|---|
asyncAction
| Call with args | Any Promise workflow; cache/polling factories; custom fetch logic. |
fetchAction / getAction
| Call with params | Declarative HTTP config on top of asyncAction. See fetch-actions. |
asyncAtom
| Read like an atom | Keyed auto-fetch from atom deps; refetch/cancel. See State → asyncAtom. |
Full API quick reference
import { asyncAction } from 'mates';
const fetchUser = asyncAction(async (id: string) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`, {
signal: fetchUser.abortController.signal,
});
if (!res.ok) throw new Error('Not found');
return res.json() as Promise<{ id: number; name: string }>;
}, { cacheLimit: 5, pollInterval: 4000 });
fetchUser.isLoading()
fetchUser.status() // "init" | "loading" | "success" | "error"
fetchUser.data()
fetchUser.error()
fetchUser('1');
fetchUser.cancel(); // abort() the current AbortController
fetchUser.cache('1'); // skip network on cache hit
fetchUser.clearCache('1');
fetchUser.startPolling('1');
fetchUser.stopPolling();
fetchUser.subscribe(() => console.log(fetchUser.status()), true); // success only
fetchUser.interceptBefore((next, id) => next(String(id).trim()));
fetchUser.interceptAfter((user) => ({ ...user, loadedAt: Date.now() }));
data / isLoading / error / status + interceptAfter
Real GET against jsonplaceholder. interceptAfter stamps loadedAt. status walks init → loading → success | error. User 999 is a 404.
cancel() aborts abortController
The fn listens on fetchUser.abortController.signal. cancel() aborts that controller, drops the result, and sets status back to init.