订阅句柄与事件值(Subscription)
每次订阅产出一个 subscription 句柄,事件名在值位产出一个事件值。句柄管退订与统计,事件值管把频道当数据传递。
event Ticked(n: int);
event MovedX(dx: int);
var total = 0;
func Add(n: int)
{
print($"加 {n}");
}
func Track(n: int)
{
total += n;
}订阅句柄的三个成员
~> / <~ / once ~> 表达式的值都是 subscription:Cancel() 退订,IsCancelled 查状态,TriggerCount 数触发次数:
val h: subscription = Ticked ~> Add;
emit Ticked(1);
print("已触发", h.TriggerCount, "取消?", h.IsCancelled);
h.Cancel();
emit Ticked(2);
print("取消?", h.IsCancelled);
h.Cancel();加 1
已触发 1 取消? False
取消? True取消后再 emit 不再送达,重复 Cancel() 是无害的。
once:触发一次自动退
once ~> 订阅在首次触发后自动转已取消:
val single = Ticked once ~> Add;
emit Ticked(10);
emit Ticked(20);
print("once 取消?", single.IsCancelled, "次数", single.TriggerCount);加 10
once 取消? True 次数 1匿名 lambda 的退订
匿名 lambda 订阅同样拿到句柄,保存句柄即可退订:
val lh = Ticked ~> (n: int) => { total += n; };
emit Ticked(100);
lh.Cancel();
emit Ticked(1000);
print("total =", total);total = 100事件一等值
事件名出现在值位就是事件值,类型是形状类型 event<P...>。相等按声明身份判定(同声明才相等),emit 经值发射照跑声明管线:
val v: event<int> = MovedX;
print(v == MovedX);
emit v(7);True「一组频道」可以用事件值列表表达,循环订阅、循环退订:
val watch: list<event<int>> = [MovedX, Ticked];
for e in watch
{
e ~> Track;
}
emit MovedX(3);
emit Ticked(4);
print("total =", total);total = 107注意
- 事件值的载荷形状必须相同:多、少、位型不符都不能互赋。
eventof(obj.Prop)把 event prop 频道取成event<T, T>值(载荷旧值、新值),之后与普通事件值同用。- 泛型事件的类型实参从 handler 形参或 emit 实参推断。
最后更新于 2026年10月10日
