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

<Meta title='@dxtmisha/functional/ru/Classes/CacheItem'/>

# Класс CacheItem

Низкоуровневый класс для управления одним кешированным значением с автоматической инвалидацией на основе данных сравнения. Этот класс используется внутри класса Cache, но также может использоваться напрямую для точного контроля кеша.

## Основные возможности

- **Кеширование одного значения** — управляет одним кешированным значением с интеллектуальной инвалидацией
- **Инвалидация на основе сравнения** — автоматически инвалидирует кеш при изменении данных сравнения
- **Отслеживание предыдущего значения** — сохраняет ссылку на старое кешированное значение во время обновлений
- **Поддержка синхронного и асинхронного режимов** — выполнение как синхронных, так и асинхронных callback
- **Типобезопасность** — полная поддержка TypeScript с дженериками
- **Эффективное использование памяти** — минимальные накладные расходы для хранения одного значения

## Конструктор

### `constructor`

Создаёт новый экземпляр CacheItem с предоставленной callback функцией.

**Параметры:**
- `callback: () => T` — функция для выполнения когда кеш нужно сгенерировать или обновить

```javascript
import { CacheItem } from '@dxtmisha/functional'

// Простой элемент кеша для дорогих вычислений
const expensiveComputation = new CacheItem(() => {
  console.log('Выполнение дорогих вычислений...')
  return Math.random() * 1000
})

// Элемент кеша для API данных
const apiData = new CacheItem(() => {
  console.log('Получение из API...')
  return fetch('/api/data').then(r => r.json())
})
```

## Методы получения данных

### `getCache`

Получает кешированные данные или выполняет callback для генерации новых данных если кеш недействителен.

**Параметры:**
- `comparison: any[]` — массив значений, используемых для сравнения при инвалидации кеша

**Возвращает:** `T` — кешированные данные или результат выполнения callback

```javascript
const userCache = new CacheItem(() => {
  console.log('Загрузка данных пользователя...')
  return { id: 1, name: 'Иван Иванов', role: 'admin' }
})

let userId = 1
let userRole = 'admin'

// Первый вызов - выполняет callback
const user1 = userCache.getCache([userId, userRole])
console.log(user1) // Лог: "Загрузка данных пользователя..." затем возвращает объект пользователя

// Второй вызов с тем же сравнением - возвращает кешированные данные
const user1Cached = userCache.getCache([userId, userRole])
console.log(user1Cached) // Возвращает кешированные данные без логирования

// Изменение данных сравнения - кеш инвалидирован
userId = 2
const user2 = userCache.getCache([userId, userRole])
console.log(user2) // Лог: "Загрузка данных пользователя..." затем возвращает новый объект пользователя
```

### `getCacheAsync`

Асинхронно получает кешированные данные или выполняет асинхронный callback для генерации новых данных.

**Параметры:**
- `comparison: any[]` — массив значений, используемых для сравнения при инвалидации кеша

**Возвращает:** `Promise<T>` — промис, разрешающийся в кешированные данные или результат callback

```javascript
const apiCache = new CacheItem(async () => {
  console.log('Получение пользователя из API...')
  const response = await fetch('/api/user/1')
  return await response.json()
})

// Первый вызов - выполняет асинхронный callback
const user = await apiCache.getCacheAsync([])
console.log(user) // Лог: "Получение пользователя из API..." затем возвращает данные пользователя

// Второй вызов - возвращает кешированные данные
const userCached = await apiCache.getCacheAsync([])
console.log(userCached) // Возвращает кешированные данные без API вызова
```

### `getCacheOld`

Возвращает предыдущее кешированное значение (до последнего обновления).

**Возвращает:** `T | undefined` — предыдущее кешированное значение или undefined если нет предыдущего значения

```javascript
const dataCache = new CacheItem(() => ({ timestamp: Date.now() }))

// Получить начальные данные
const data1 = dataCache.getCache(['v1'])
console.log(dataCache.getCacheOld()) // undefined (нет предыдущего значения)

// Обновить кеш с новым сравнением
const data2 = dataCache.getCache(['v2'])
console.log(dataCache.getCacheOld()) // Возвращает data1 (предыдущее значение)

// Обновить снова
const data3 = dataCache.getCache(['v3'])
console.log(dataCache.getCacheOld()) // Возвращает data2 (предыдущее значение)
```

## Практические примеры

### Кеширование вычислений

```javascript
const expensiveCache = new CacheItem(() => {
  console.log('Выполнение дорогих вычислений...')
  return Array.from({length: 1000000}, (_, i) => i * i).reduce((a, b) => a + b)
})

let factor = 1
let data = [1, 2, 3]

// Первый вызов
const result1 = expensiveCache.getCache([factor, data])
console.log('Результат:', result1)

// Кешированный вызов
const result2 = expensiveCache.getCache([factor, data])
console.log('Кешированный:', result2) // Без пересчета
```

### Валидация с историей

```javascript
const validationCache = new CacheItem(() => {
  const errors = []
  if (!this.value) errors.push('Поле обязательно')
  if (this.value.length < 3) errors.push('Минимум 3 символа')
  return { isValid: errors.length === 0, errors }
})

function validateField(value) {
  this.value = value
  const current = validationCache.getCache([value])
  const previous = validationCache.getCacheOld()

  return { current, previous, hasChanged: previous && current !== previous }
}

// Использование
console.log(validateField('ab')) // Показывает ошибки
console.log(validateField('abc')) // Валидный результат
```

### Асинхронные данные

```javascript
const apiCache = new CacheItem(async () => {
  const response = await fetch('/api/data')
  return response.json()
})

async function getData(userId) {
  return await apiCache.getCacheAsync([userId])
}

// Использование
const data = await getData(1) // API вызов
const cached = await getData(1) // Кешированные данные
```

Класс CacheItem предоставляет низкоуровневый контроль над кешированием одного значения с мощными возможностями инвалидации и отслеживания истории изменений.
