import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/ru/functional-basic/Classes/StorageCallback - Обратные вызовы хранилища'/>

# Класс StorageCallback

Вспомогательный класс для управления группами функций обратного вызова, связанных с конкретными ключами хранилища. Он позволяет нескольким компонентам или функциям реагировать на изменения или триггеры хранилища согласованно и асинхронно.

## Основные особенности

- **Именованные экземпляры** — реализует паттерн, похожий на синглтон, где экземпляры извлекаются по имени и группе, гарантируя, что разные части приложения используют один и тот же список обратных вызовов для одного и того же ресурса.
- **Разделение по группам** — позволяет разделять списки обратных вызовов по группам (например, 'main', 'global', 'local'), предотвращая конфликты имен между различными модулями.
- **Асинхронное выполнение** — поддерживает асинхронные обратные вызовы и выполняет их последовательно в процессе вызова `run`.
- **Отслеживание состояния загрузки** — предоставляет встроенный флаг `loading`, который автоматически переключается во время фазы выполнения обратных вызовов.

## Инициализация

Для инициализации объекта вызовите конструктор `StorageCallback(name, group)` или используйте статический метод `getInstance(name, group)`.

### Ограничения типов (Generics)

Для обеспечения строгой типизации класс поддерживает следующие параметры:
- `T = any` — тип данных, передаваемых в обратные вызовы.
- `Callback = (value: T) => void | Promise<void>` — структура функции обратного вызова.

**Параметры:**
- `name: string` — уникальный идентификатор для записи в хранилище.
- `group: string = 'main'` — необязательная категория для предотвращения конфликтов имен.

```typescript
import { StorageCallback } from '@dxtmisha/functional-basic'

// 1. Простая инициализация (группа по умолчанию 'main')
const storage = new StorageCallback('user-data')

// 2. Использование статического метода getInstance
const sharedStorage = StorageCallback.getInstance('settings', 'global')

// 3. Использование generic-типов для строгой типизации
const numberStorage = new StorageCallback<number>('counter')
numberStorage.addCallback((val) => console.log(val + 1))
```

## Методы

### Информация

- `getName(): string` — возвращает имя экземпляра хранилища.
- `isLoading(): boolean` — возвращает текущее состояние загрузки.
- `getLoading(): boolean` — возвращает текущее состояние загрузки (аналог `isLoading`).

### Управление

- `addCallback(callback: Callback, isOnce?: boolean): this` — добавляет новый обратный вызов в список выполнения. При `isOnce: true` callback будет удален после первого выполнения.
- `removeCallback(callback: Callback): this` — удаляет конкретный обратный вызов из списка.

### Управление процессом (Control)

- `preparation(): this` — подготавливает состояние перед выполнением (устанавливает `loading` в `true`). Используется вручную при запуске асинхронных операций.
- `run(value: T): Promise<this>` — последовательно выполняет все обратные вызовы с переданным значением. В начале выполнения устанавливает `loading` в `false`.

## Примеры использования

### Ручное управление состоянием загрузки

Если данные загружаются асинхронно из внешнего источника (например, Figma storage), вы можете управлять состоянием `loading` вручную.

```typescript
const storage = new StorageCallback('figma-data')

// 1. Проверяем, не идет ли уже загрузка
if (!storage.isLoading()) {
  // 2. Устанавливаем состояние загрузки
  storage.preparation()
  
  // 3. Запрашиваем данные
  fetchFromFigma((data) => {
    // 4. Выполняем колбэки (run сбросит loading в false)
    storage.run(data)
  })
}
```

### Одноразовый обратный вызов

Если вам нужно, чтобы функция сработала только один раз (например, для начальной загрузки данных), используйте флаг `isOnce`.

```typescript
const storage = new StorageCallback('initial-data')

storage.addCallback((data) => {
  console.log('Выполнено один раз:', data)
}, true)

await storage.run('update 1') // 'Выполнено один раз: update 1'
await storage.run('update 2') // (ничего не выводится, callback удален)
```
