refactor: addInterrupt is now on GameHost

This commit is contained in:
hypercross 2026-04-04 15:37:22 +08:00
parent 60a6bcad77
commit 775bb00bed
4 changed files with 40 additions and 5 deletions

View File

@ -57,7 +57,7 @@ effect(() => {
const animation = playAnimationForState(state);
// 为下一个 produceAsync 注册 interruption
host.state.addInterruption(animation);
host.addInterruption(animation);
});
```
@ -74,13 +74,16 @@ async function placePieceAsync(context: MutableSignal<GameState>, row: number, c
}
```
## MutableSignal 中断 API
## 中断 API
`GameHost` 直接暴露了以下方法,供 UI 层调用:
| 方法 | 说明 |
|---|---|
| `addInterruption(promise: Promise<void>)` | 添加中断 Promise`produceAsync` 会等待它完成 |
| `addInterruption(promise: Promise<void>)` | 注册中断,下一个 `produceAsync` 会等待它 |
| `clearInterruptions()` | 清除所有未完成的中断 |
| `produceAsync(fn: (draft: T) => void): Promise<void>` | 等待所有 interruption 完成后更新状态 |
`MutableSignal` 上还有 `produceAsync`,逻辑层使用。
## 注意事项

View File

@ -64,6 +64,10 @@
|---|---|
| `value: T` | 获取当前值(继承自 Signal |
| `produce(fn: (draft: T) => void): void` | 同步不可变更新 |
| `addInterruption(promise: Promise<void>): void` | 添加中断 Promise`produceAsync` 会等待它完成 |
| `addInterruption(promise: Promise<void>): void` | 添加中断,`produceAsync` 会等待它 |
| `clearInterruptions(): void` | 清除所有未完成的中断 |
| `produceAsync(fn: (draft: T) => void): Promise<void>` | 等待所有 interruption 完成后更新状态 |
### GameHost 上的中断方法
`GameHost` 直接代理了 `addInterruption``clearInterruptions`,供 UI 层使用,无需访问内部 `MutableSignal`。详见 [动画与状态更新同步](./animation-sync.md)。

View File

@ -149,3 +149,15 @@ while (host.status.value === 'running' && host.activePromptSchema.value) {
## 动画同步
如需在状态更新之间播放动画,参考 [动画与状态更新同步](./animation-sync.md)。
`GameHost` 提供了两个方法:
| 方法 | 说明 |
|---|---|
| `addInterruption(promise: Promise<void>)` | 注册动画中断,下一个 `produceAsync` 会等待它 |
| `clearInterruptions()` | 清除所有未完成的中断 |
```ts
// UI 层:检测到状态变化后播放动画并注册中断
host.addInterruption(playAnimation('place', data));
```

View File

@ -79,6 +79,22 @@ export class GameHost<TState extends Record<string, unknown>> {
return this.commands._tryCommit(input);
}
/**
* produceAsync Promise UI
* @see MutableSignal.addInterruption
*/
addInterruption(promise: Promise<void>): void {
this._state.addInterruption(promise);
}
/**
*
* @see MutableSignal.clearInterruptions
*/
clearInterruptions(): void {
this._state.clearInterruptions();
}
async setup(setupCommand: string): Promise<void> {
if (this._isDisposed) {
throw new Error('GameHost is disposed');