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

<Meta title='@dxtmisha/vi/functional-basic/Classes/StorageCallback - Storage Callbacks'/>

# Lớp StorageCallback

Một lớp tiện ích để quản lý các nhóm hàm callback liên kết với các khóa lưu trữ cụ thể. Nó cho phép nhiều thành phần hoặc chức năng phản hồi các thay đổi hoặc kích hoạt lưu trữ một cách phối hợp, bất đồng bộ.

## Các đặc điểm chính

- **Các thực thể có tên** — thực hiện mô hình singleton, trong đó các thực thể được truy xuất theo tên và nhóm, đảm bảo rằng các phần khác nhau của ứng dụng chia sẻ cùng một danh sách callback cho cùng một tài nguyên.
- **Phân tách theo nhóm** — cho phép tách biệt các danh sách callback theo nhóm (ví dụ: 'main', 'global', 'local'), ngăn chặn xung đột tên giữa các mô-đun khác nhau.
- **Thực thi bất đồng bộ** — hỗ trợ các callback dựa trên `Promise` và thực thi chúng theo trình tự trong quá trình `run`.
- **Theo dõi trạng thái tải** — cung cấp cờ `loading` có sẵn, được quản lý tự động trong giai đoạn thực thi callback.

## Khởi tạo

Để khởi tạo đối tượng, hãy gọi hàm tạo `StorageCallback(name, group)` hoặc sử dụng phương thức tĩnh `getInstance(name, group)`.

### Các ràng buộc Generic

Để đảm bảo kiểu dữ liệu nghiêm ngặt, lớp hỗ trợ các generic sau:
- `T = any` — Kiểu dữ liệu được truyền cho các callback.
- `Callback = (value: T) => void | Promise<void>` — Cấu trúc hàm callback.

**Tham số:**
- `name: string` — định danh duy nhất cho mục nhập lưu trữ.
- `group: string = 'main'` — phân loại tùy chọn để ngăn chặn xung đột tên.

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

// 1. Khởi tạo đơn giản (nhóm mặc định là 'main')
const storage = new StorageCallback('user-data')

// 2. Sử dụng phương thức tĩnh getInstance
const sharedStorage = StorageCallback.getInstance('settings', 'global')

// 3. Sử dụng generic để kiểm soát kiểu dữ liệu
const numberStorage = new StorageCallback<number>('counter')
numberStorage.addCallback((val) => console.log(val + 1))
```

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

### Thông tin

- `getName(): string` — trả về tên của thực thể lưu trữ.
- `isLoading(): boolean` — trả về trạng thái tải hiện tại.
- `getLoading(): boolean` — trả về trạng thái tải hiện tại (tương tự `isLoading`).

### Quản lý

- `addCallback(callback: Callback, isOnce?: boolean): this` — thêm một callback mới vào danh sách thực thi. Nếu `isOnce: true`, callback sẽ bị xóa sau lần thực thi đầu tiên.
- `removeCallback(callback: Callback): this` — xóa một callback cụ thể khỏi danh sách.

### Điều khiển (Control)

- `preparation(): this` — chuẩn bị trạng thái trước khi thực thi (đặt `loading` thành `true`). Được sử dụng thủ công khi bắt đầu các hoạt động bất đồng bộ.
- `run(value: T): Promise<this>` — thực thi tất cả các callback theo trình tự với giá trị được cung cấp. Đặt `loading` về `false` khi bắt đầu thực thi.

## Ví dụ sử dụng

### Quản lý trạng thái tải thủ công

Khi dữ liệu được lấy bất đồng bộ từ nguồn bên ngoài (ví dụ: Figma storage), bạn có thể quản lý trạng thái `loading` thủ công để điều phối nhiều yêu cầu.

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

// 1. Kiểm tra nếu không phải đang tải
if (!storage.isLoading()) {
  // 2. Thiết lập trạng thái đang tải
  storage.preparation()
  
  // 3. Yêu cầu dữ liệu
  fetchFromFigma((data) => {
    // 4. Thực thi callback (run sẽ đưa loading về false)
    storage.run(data)
  })
}
```

### Callback một lần

Nếu bạn chỉ cần một hàm kích hoạt một lần (ví dụ: để nạp dữ liệu ban đầu), hãy sử dụng cờ `isOnce`.

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

storage.addCallback((data) => {
  console.log('Đã thực thi một lần:', data)
}, true)

await storage.run('update 1') // 'Đã thực thi một lần: update 1'
await storage.run('update 2') // (không có đầu ra, callback đã bị xóa)
```
