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

<Meta title='@dxtmisha/vi/functional/Classes/DesignAsyncAbstract - Lớp thiết kế bất đồng bộ cơ sở'/>

# Lớp DesignAsyncAbstract

Một lớp cơ sở trừu tượng bất đồng bộ để quản lý các thuộc tính của constructor và thay đổi trạng thái. Nó mở rộng `DesignAbstract` để hỗ trợ khởi tạo sự kiện bất đồng bộ, lý tưởng cho các thiết kế yêu cầu lấy dữ liệu hoặc tính toán bất đồng bộ.

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

- **Khởi tạo bất đồng bộ** — hỗ trợ khởi tạo sự kiện dựa trên `Promise` thông qua `initEvent`.
- **Quản lý thuộc tính** — kế thừa việc xử lý có cấu trúc dữ liệu đầu vào (`props`) và lưu trữ sự kiện (`event`).
- **Luồng công việc bất đồng bộ** — đảm bảo rằng các callback chỉ được kích hoạt sau khi quá trình chuẩn bị trạng thái bất đồng bộ hoàn tất.

## Khởi tạo

`DesignAsyncAbstract` là một lớp trừu tượng và không thể được khởi tạo trực tiếp. Nó được thiết kế để mở rộng bởi các lớp khác, các lớp này phải triển khai phương thức `initEvent` để chuẩn bị dữ liệu bất đồng bộ.

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

Lớp này sử dụng hai loại generic để đảm bảo kiểu dữ liệu nghiêm ngặt:
- `T extends Record<string, any>` — Kiểu cho các thuộc tính đầu vào (`props`). Xác định cấu trúc dữ liệu được truyền vào hàm khởi tạo.
- `C extends Record<string, any>` — Kiểu cho trạng thái nội bộ hoặc bộ nhớ đệm (`event`). Xác định cấu trúc dữ liệu sẽ có sẵn trong các hàm gọi lại sau khi khởi tạo bất đồng bộ.

**Tham số hàm khởi tạo:**
- `props: T` — một đối tượng chứa dữ liệu ban đầu.
- `callback?: (event: C) => void` — một hàm gọi lại sẽ được gọi sau mỗi lần cập nhật thành công (bao gồm cả cập nhật bất đồng bộ).
- `changed?: string[]` — danh sách các khóa từ `props` cần theo dõi (tùy chọn). Nếu không được cung cấp, tất cả các khóa trong `props` sẽ được theo dõi.

**Thuộc tính nội bộ:**
- `protected readonly event: C` — đối tượng trạng thái. Đây là nơi bạn nên đổ dữ liệu vào trong `initEvent`. Nó sẽ được truyền vào `callback`.

**Phương thức bắt buộc phải triển khai:**
- `protected abstract initEvent(): Promise<void>` — một phương thức bất đồng bộ được gọi mỗi khi các thuộc tính được theo dõi thay đổi. Đây là nơi `this.event` nên được chuẩn bị.

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

// 1. Xác định các interface
interface MyProps { userId: number }
interface MyState { userName: string; avatar: string }

// 2. Triển khai một lớp cụ thể
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. Sử dụng
const user = new UserDesign(
  { userId: 1 }, 
  (state) => {
    console.log('Dữ liệu người dùng đã được tải:', state.userName)
  },
  ['userId'] // Chỉ theo dõi thay đổi của userId
)
```

## Các phương thức quản lý dữ liệu

### `make`

Khởi tạo quá trình cập nhật callback bất đồng bộ. Nó gọi `makeCallback` (mà không đợi nó hoàn thành) và trả về instance để có thể thực hiện chuỗi lệnh (chaining).

**Tham số:**
- `compelled?: boolean` — nếu là `true`, sẽ ép buộc cập nhật dữ liệu bất kể có phát hiện thay đổi hay không.

**Trả về:** `this`

### `makeCallback`

Logic thực thi bất đồng bộ chính để cập nhật trạng thái. Nó đợi `initEvent` hoàn thành trước khi kích hoạt các callback và cập nhật trình theo dõi thay đổi.

**Tham số:**
- `compelled?: boolean` — ép buộc cập nhật dữ liệu.

**Trả về:** `Promise<void>`

## Các phương thức được bảo vệ (cho lớp kế thừa)

Các phương thức này có sẵn trong các lớp con để quản lý logic cập nhật.

### `is`

Kiểm tra sự tồn tại của một khóa trong đối tượng `props`.

**Tham số:**
- `name: keyof T` — tên thuộc tính.

**Trả về:** `boolean`

### `isChanged`

Kiểm tra xem giá trị của một thuộc tính cụ thể có thay đổi so với trạng thái trước đó hay không. Hữu ích bên trong `initEvent` để tối ưu hóa các yêu cầu (chỉ thực hiện hành động nếu một ID cụ thể đã thay đổi).

**Tham số:**
- `name: keyof C` — tên thuộc tính trong trạng thái.
- `nameProp?: keyof T | (keyof T)[]` — tên hoặc danh sách tên các thuộc tính trong `props` mà sự thay đổi dựa trên đó. Mặc định trùng với `name`.

**Trả về:** `boolean`

### `makeCallbackItem`

Thực thi hàm callback đã được truyền vào constructor.

**Trả về:** `void`

### `initEvent` (trừu tượng)

Phương thức bất đồng bộ phải được triển khai trong lớp con. Nó sẽ gán dữ liệu cho `this.event` dựa trên `this.props`.

**Trả về:** `Promise<void>`
