Files
endorphin-tessera-gui/examples/owned-tasks.endor
T

46 lines
3.5 KiB
Plaintext

// owner 作用域决定取消时机:Page 关闭会取消其任务,隐藏 Block 和 ui 的任务可继续。
// 每个 owner 下同 key 的重复点击替换旧定时器;任务生命周期不由画面是否可见推断。
// 把 owner 与要修改的 state 分开持有,使同一个调度方法可用于三个作用域。
class Actions {
// 保存任务的生命周期归属,不一定等于回调接收者 self;schedule 把它作为 ui.after 第一参。
owner: Object
// 回调实际修改的共享计数,与 owner 分开,三个 Actions 可以修改同一状态但有不同取消边界。
state: Object
// 定时任务成功交付后修改共享计数,零参数签名符合 timer 回调要求。
// 任务调度器用已绑定 self 的 complete 零参调用,timer 不额外传 Event;自有 state 的增量是交付后的业务修改。
function complete(self: Actions): Unit { self.state.increment() }
// 每次启动 1500ms 的 load 定时器;相同 owner/key 只有最新任务继续等待。
// 三个按钮的 click 事件路由调用 schedule,event 为事件参数;方法内部不读取它,只创建延时任务。
function schedule(self: Actions, event: Event): Unit {
// 返回句柄未存入字段也不立即取消,调度器继续维护任务;同一 owner/load 新任务替换旧等待。
ui.after(self.owner, "load", 1500, self.complete)
}
}
// 唯一业务计数,三种 owner 的成功回调都递增此对象,文字绑定显示同一个 value。
state = ui.state(0)
// 该 Block 从未进入页面树,但全局引用仍持有它,因此它拥有的任务可执行。
hidden = TextBlock("这个 Block 没有挂载,也能拥有任务")
page = Page()
page.title = "任务生命周期"
// 三个 Action 共享一个 state,却分别归属 Page、Block、应用,便于比较关闭页面的取消边界。
// Page 仍在窗口注册表中才具备此 owner 的交付资格,单纯切换标签不等于关闭 Page。
pageActions = Actions(page, state)
// hidden 是普通 Block,未挂载不阻止其拥有任务;全局引用和 Actions 字段保留业务对象。
blockActions = Actions(hidden, state)
// 应用 owner 使用 ui,页面关闭后仍可交付,但整个运行时退出时会统一取消未完成任务。
appActions = Actions(ui, state)
pageButton = Button("Page 任务:关闭 Tab 会取消")
blockButton = Button("隐藏 Block 任务:关闭 Tab 仍继续")
appButton = Button("应用任务:关闭 Tab 仍继续")
// 保存连接对象供显式监听器生命周期管理,按钮的事件路由先调用对应 Actions.schedule 再安装定时器。
pageConnection = pageButton.on("click", pageActions.schedule)
// 监听器绑定 blockActions,实际任务 owner 来自该实例字段 hidden,不误用触发点击的按钮 Mount。
blockConnection = blockButton.on("click", blockActions.schedule)
// 监听器绑定 appActions,所以同一个按钮回调实现可复用而不改变三个不同 owner 身份。
appConnection = appButton.on("click", appActions.schedule)
page.render(Column(24, 16, TextBlock("1.5 秒后更新同一个状态对象;重复点击只保留最新任务"), ui.textOf(state, "value"), pageButton, blockButton, appButton))
// 额外应用级任务延迟 500ms,用于展示没有点击也可按 worker 空闲轮询交付。
// key=initial 与应用按钮的 key=load 不同,不会因启动演示定时器而取消后续 load 任务。
initial = ui.after(ui, "initial", 500, appActions.complete)
ui.window().setTitle("Owned Tasks")