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

<Meta title='@dxtmisha/ru/functional/Classes/DesignAsyncAbstract - Базовый асинхронный класс дизайна'/>

# Класс DesignAsyncAbstract

Асинхронный абстрактный базовый класс для управления свойствами конструктора и изменениями состояния. Расширяет `DesignAbstract` поддержкой асинхронной инициализации событий, что делает его идеальным для случаев, требующих загрузки данных или асинхронных вычислений.

## Ключевые особенности

- **Асинхронная инициализация** — поддержка инициализации событий на основе `Promise` через метод `initEvent`.
- **Управление свойствами** — наследует структурированную обработку входных данных (`props`) и хранилища событий (`event`).
- **Асинхронный рабочий процесс** — гарантирует, что обратные вызовы запускаются только после завершения асинхронной подготовки состояния.

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

`DesignAsyncAbstract` является абстрактным классом и не может быть инициализирован напрямую. Он предназначен для расширения другими классами, которые должны реализовать метод `initEvent` для асинхронной подготовки данных.

### Ограничения дженериков (Generic Constraints)

Класс использует два типа дженериков для обеспечения строгой типизации:
- `T extends Record<string, any>` — Тип для входных свойств (`props`). Определяет структуру данных, передаваемых в конструктор.
- `C extends Record<string, any>` — Тип для внутреннего состояния или кэша (`event`). Определяет структуру данных, которая будет доступна в обратных вызовах после асинхронной инициализации.

**Параметры конструктора:**
- `props: T` — объект с исходными данными.
- `callback?: (event: C) => void` — функция обратного вызова, которая будет вызываться после каждого успешного обновления (включая асинхронное).
- `changed?: string[]` — необязательный список ключей из `props`, за которыми нужно следить. Если не передан, отслеживаются все ключи `props`.

**Внутренние свойства:**
- `protected readonly event: C` — объект состояния. Именно его следует наполнять данными в `initEvent`. Он будет передан в `callback`.

**Обязательный метод для реализации:**
- `protected abstract initEvent(): Promise<void>` — асинхронный метод, вызываемый при изменении отслеживаемых свойств. Здесь должна происходить подготовка данных `this.event`.

```typescript
import { DesignAsyncAbstract } from '@dxtmisha/functional'

// 1. Определение интерфейсов
interface MyProps { userId: number }
interface MyState { userName: string; avatar: string }

// 2. Реализация конкретного класса
class UserDesign extends DesignAsyncAbstract<MyProps, MyState> {
  protected async initEvent(): Promise<void> {
    const response = await fetch(`https://api.example.com/users/${this.props.userId}`)
    const data = await response.json()
    
    this.event.userName = data.name
    this.event.avatar = data.image
  }
}

// 3. Использование
const user = new UserDesign(
  { userId: 1 }, 
  (state) => {
    console.log('Данные пользователя загружены:', state.userName)
  },
  ['userId'] // Следить только за изменением userId
)
```

## Методы управления данными

### `make`

Инициирует асинхронный процесс обновления. Вызывает `makeCallback` (не дожидаясь завершения) и возвращает экземпляр для цепочки вызовов.

**Параметры:**
- `compelled?: boolean` — если `true`, принудительно обновляет данные независимо от наличия изменений.

**Возвращает:** `this`

### `makeCallback`

Основная асинхронная логика выполнения для обновления состояния. Дожидается завершения `initEvent` перед запуском обратных вызовов и обновлением трекера изменений.

**Параметры:**
- `compelled?: boolean` — принудительно обновляет данные.

**Возвращает:** `Promise<void>`

## Защищенные методы (для наследников)

### `is`

Проверяет наличие ключа в объекте `props`.

**Параметры:**
- `name: keyof T` — имя свойства.

**Возвращает:** `boolean`

### `isChanged`

Проверяет, изменилось ли значение указанного свойства по сравнению с предыдущим состоянием. Полезно внутри `initEvent` для оптимизации запросов (выполнять действие, только если конкретный ID изменился).

**Параметры:**
- `name: keyof C` — имя свойства в состоянии.
- `nameProp?: keyof T | (keyof T)[]` — имя или список имен свойств в `props`, на основе которых рассчитывается изменение. По умолчанию совпадает с `name`.

**Возвращает:** `boolean`

### `makeCallbackItem`

Выполняет вызов функции обратного вызова, переданной в конструктор.

**Возвращает:** `void`

### `initEvent` (абстрактный)

Асинхронный метод, который должен быть реализован в подклассе. В нем происходит заполнение объекта `this.event` на основе `this.props`.

**Возвращает:** `Promise<void>`

