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

<Meta title='@dxtmisha/vi/functional-basic/Classes/CacheItem - Quản lý Bộ nhớ đệm Nâng cao'/>

# Lớp CacheItem

> **⚠️ Đã lỗi thời** — Lớp này đã lỗi thời và không nên được sử dụng.

Hệ thống cốt lõi quản lý từng mục lưu trữ bộ nhớ đệm (cache) riêng biệt. Trong khi `Cache` và `CacheStatic` cung cấp các giao diện công khai để truy xuất dữ liệu cache trong toàn bộ ứng dụng, thì lớp `CacheItem` đảm nhận việc quản lý an toàn vòng đời, lưu trữ và các quy tắc vô hiệu hóa (invalidation) cho từng giá trị cụ thể.

> `CacheItem` là một **lớp phụ trợ**, được thiết kế để quản lý nội bộ các mục lưu trữ bộ nhớ đệm riêng lẻ. Trong hầu hết các trường hợp, bạn nên tương tác với bộ nhớ đệm thông qua các lớp `Cache` hoặc `CacheStatic`.

## Các tính năng chính

- **Theo dõi phụ thuộc** — duy trì các mảng so sánh để xác định xem giá trị được lưu trong bộ nhớ đệm có còn hiệu lực hay không.
- **Tính toán lười (Lazy Evaluation)** — đảm bảo rằng hàm callback (vốn có thể tốn kém tài nguyên) chỉ chạy khi các thành phần phụ thuộc thực sự thay đổi.
- **Bộ nhớ lịch sử** — giữ lại tham chiếu đến giá trị đã lưu trước đó (`getCacheOld`) ngay cả khi quá trình tính toán lại đã diễn ra.
- **Hỗ trợ Async** — xử lý tự nhiên cả việc nạp dữ liệu đồng bộ (`getCache`) và bất đồng bộ dựa trên `Promise` (`getCacheAsync`).
- **Vô hiệu hóa nghiêm ngặt** — sử dụng logic so sánh sâu để chỉ kích hoạt cập nhật khi thực sự cần thiết.

## Khởi tạo

Là một thành phần phụ trợ, `CacheItem` thường được khởi tạo bởi các trình quản lý cấp cao hơn. Tuy nhiên, nó có thể được tạo thủ công nếu yêu cầu logic lưu trữ bộ nhớ đệm riêng biệt và tùy chỉnh.

### Ràng buộc Generic (Generic Constraints)

Lớp hỗ trợ generic sau để đảm bảo kiểm soát kiểu dữ liệu nghiêm ngặt cho giá trị được lưu:
- `T` — Kiểu dữ liệu của giá trị được lưu trong bộ nhớ đệm.

**Tham số:**
- `callback: () => T` — một hàm sẽ tạo hoặc lấy dữ liệu cho bộ nhớ đệm.

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

// 1. Khởi tạo với một hàm truy xuất dữ liệu
const userCache = new CacheItem(() => fetchUserData())

// 2. Sử dụng generic để kiểm soát kiểu dữ liệu nghiêm ngặt
const numberCache = new CacheItem<number>(() => Math.random())
```

## Các phương thức

### Truy cập Bộ nhớ đệm

- `getCache(comparison?: any[]): T` — Lấy giá trị từ bộ nhớ đệm. Nếu các thành phần phụ thuộc trong mảng `comparison` thay đổi, nó sẽ kích hoạt tính toán lại.
- `getCacheAsync(comparison?: any[]): Promise<T>` — Phiên bản bất đồng bộ của `getCache`. Trả về một Promise giải quyết thành dữ liệu đã lưu hoặc dữ liệu mới được lấy về.

### Lịch sử

- `getCacheOld(): T | undefined` — Trả về giá trị đã được lưu trong bộ nhớ đệm ngay trước lần cập nhật cuối cùng.

## Ví dụ

### Vô hiệu hóa dựa trên phụ thuộc
```javascript
let count = 0
const counterCache = new CacheItem(() => ++count)

// Gọi lần đầu: tính toán và lưu cache giá trị 1
counterCache.getCache([10]) // trả về 1

// Gọi lần hai: các thành phần phụ thuộc khớp với [10], trả về giá trị 1 đã lưu
counterCache.getCache([10]) // trả về 1

// Gọi lần ba: các thành phần phụ thuộc thay đổi thành [20], tính toán và lưu cache giá trị 2
counterCache.getCache([20]) // trả về 2

// Kiểm tra lịch sử:
console.log(counterCache.getCacheOld()) // trả về 1
```

### Cấu hình Cache cho API Async
```javascript
const apiCache = new CacheItem(async () => {
  const response = await fetch('/api/data')
  return response.json()
})

// Lấy dữ liệu từ mạng cho yêu cầu 'v1' đầu tiên
const data1 = await apiCache.getCacheAsync(['v1'])

// Trả về từ bộ nhớ đệm ngay lập tức cho các yêu cầu 'v1' tiếp theo
const data2 = await apiCache.getCacheAsync(['v1'])
```
