Запросы
import { createQuery } from 'effector-refetch';
const query = createQuery({
effect, // Effect<Params, Result, Error> (или `handler`)
initialData,
enabled, // Store<boolean>
mapData,
mapError,
contract,
validate, // см. «HTTP и валидация»
retry, // number | { times, delay?, filter?, suppressIntermediateErrors? }
cache, // true | { adapter?, staleAfter?, key?, purge?, swr?, dedupe? }
concurrency, // 'TAKE_LATEST' (по умолчанию) | 'TAKE_FIRST' | 'TAKE_EVERY'
name, // метка для devtools
});Опции
effect— вашEffect<Params, Result, Error>.handler: async params => …— сахар.concurrency— поведение при пересекающихся запусках:TAKE_LATEST(по умолчанию) — новый запуск вытесняет и прерывает предыдущий.TAKE_FIRST— игнорировать новые запуски, пока один в полёте.TAKE_EVERY— применяются все (в$dataпобеждает последний результат).
retry—numberили{ times, delay?, filter?, suppressIntermediateErrors? }. Каждый ретрай — реальный вызов эффекта. Хелперы:linearDelay,exponentialDelay.cache—trueили конфиг (см. кэширование).enabled— гейтStore<boolean>; покаfalse,start/refreshпропускаются.refetchInterval— поллинг каждые N мс (numberилиStore<number>, 0 = выкл). См. Авто-рефетч и поллинг.timeout— дедлайн одной попытки в мс (numberилиStore<number>, 0 = выкл): если прогон превысил его, запрос в полёте прерывается и прогон падает (ретраится, композируется сretry). Не путать сrefetchInterval(как часто поллить) —timeoutэто сколько может длиться одна попытка.structuralSharing— сохранять ссылочную идентичность неизменённых частей результата (меньше ре-рендеров).placeholderData— значение или(prev) => …, показываемое, пока нет реальных данных;$isPlaceholderDataравноtrueдо первого реального результата. В отличие отinitialData, не считается закэшированным.mapData/mapError— нормализация результата / ошибки перед сторами.
query.prefetch(params) прогревает кэш под params без изменения $data/$status (no-op без кэша, пропускает свежие записи) — например, префетч следующей страницы по hover.
keepPreviousData по умолчанию
$data не очищается на новый start — он держит предыдущий результат, пока не придёт новый. То есть при смене параметров старые данные остаются видимыми, пока идёт новый запрос (TanStack-овский keepPreviousData), из коробки. Для явной очистки — reset().
Разделите это между многими запросами через фабрику.
События жизненного цикла
query.finished.done; // { params, result } — запуск успешен
query.finished.fail; // { params, error } — запуск упал
query.finished.finally; // { params, status: 'done' | 'fail' }
query.aborted; // { params } — cancel / reset / вытеснение TAKE_LATEST / skipДля совместимости с farfetched finished также отдаёт:
query.finished.success; // алиас finished.done (то же событие)
query.finished.failure; // алиас finished.fail (то же событие)
query.finished.skip; // { params } — гейт `enabled` заблокировал запускfinished.skip срабатывает только на skip по гейту enabled (запрос не выполнялся). Более широкое событие aborted по-прежнему срабатывает на любой отброшенный запуск — skip, cancel, reset и вытеснение TAKE_LATEST, — оставаясь надмножеством skip. (В отличие от farfetched, finished.finally срабатывает только на done/fail, не на skip — отслеживайте skip через finished.skip / aborted.)
Операторы
concurrency / retry / cache — это ещё и отдельные композируемые операторы; inline-опции — сахар над ними. Применяйте напрямую, в том числе после создания:
import { createQuery, concurrency, retry, cache } from 'effector-refetch';
const search = createQuery({ effect: searchFx });
concurrency(search, { strategy: 'TAKE_LATEST' });
retry(search, { times: 3, delay: exponentialDelay(200) });
cache(search, { staleAfter: 30_000, purge: loggedOut });Кэширование
cache: { adapter?, staleAfter?, key?, purge?, swr?, dedupe? }
swr: true— отдать устаревшую запись сразу, ревалидировать в фоне ($staleпереходитtrue→false).dedupe: true— склеить одинаковые in-flight запросы (по ключу) в один прогон эффекта.- Адаптеры:
inMemoryCache({ maxAge?, maxEntries?, onHit?, onMiss?, onExpired?, onEvicted? })(LRU GC + события),localStorageCache({ version?, maxAge? })/sessionStorageCache(...)(поднимитеversion, чтобы инвалидировать старые данные),voidCache.
Реактивный (sourced) конфиг
Inline concurrency, retry.times, cache.staleAfter (и enabled) принимают Store вместо константы — читается реактивно и fork-корректно (каждый scope видит своё значение):
const $retries = createStore(0);
createQuery({ effect: fx, retry: { times: $retries, delay: exponentialDelay(200) } });connectQuery
connectQuery({ source, fn, target, filter? }); // один источник
connectQuery({ source: { a, b }, fn, target, filter? }); // несколько (ждёт done всех)fn получает { result, params } по каждому источнику и возвращает { params } для цели.