Скоупы
Scope — это один запущенный экземпляр состояния.
Модель описывает сторы, события, эффекты и реакции. Scope хранит фактические значения сторов. Благодаря этому одна модель может одновременно работать в приложении, тесте, SSR-запросе, виджете или фоне кешированного экрана.
Scope для чтения стора
Когда код читает count.value, стор должен понять, какую копию count вы имеете в виду. Поэтому прямое чтение и запись требуют scope в текущем контексте выполнения.
scoped(appScope, () => {
count.value += 1;
});scoped(scope, fn) открывает scope, выполняет функцию и восстанавливает предыдущий scope после завершения. Если функция возвращает promise, тот же scope сохраняется для этой promise-цепочки до ее завершения.
Один инструмент для запуска и callback-функций
scoped можно использовать сразу:
await scoped(appScope, async () => {
const response = await fetch("/api/count");
count.value = (await response.json()).count;
});А можно создать runner и переиспользовать его там, где иначе код начал бы расползаться:
const inAppScope = scoped(appScope);
await inAppScope(async () => {
count.value += 1;
});
const onMessage = inAppScope.wrap((message: string) => {
messages.items = [...messages.items, message];
});
socket.on("message", onMessage);Так один и тот же объект решает две задачи: выполнить работу прямо сейчас или сохранить callback-функцию, которая позже вернется в тот же scope.
Если код уже выполняется внутри scope, его можно не передавать:
scoped(appScope, () => {
scoped(() => {
count.value += 1;
});
});allSettled на границах
scoped удобен для обычного кода. Но когда вы запускаете юнит на границе системы — из теста, серверного загрузчика, команды или адаптера фреймворка — чаще лучше использовать allSettled.
await allSettled(incremented, {
scope: appScope,
payload: 1,
});allSettled явно показывает, какой юнит стартует, какой scope владеет состоянием и какой payload входит в граф. Он также ждет завершения асинхронной работы, поднятой этим запуском.