Files
endorphin-tessera-gui/examples/await-file.endor
T

42 lines
2.8 KiB
Plaintext

// 把 callback-free 文件 Task 与 ui.spawn 协作函数组合:await 保存执行位置,等待完成后继续,不阻塞 VM worker。
// readText 的 file 与 spawn 的 workflow 使用不同 key,分别管理读取和等待流程。
// 保存 provider Task、协程 Task 和结果;两种任务都是托管对象,可以从 Console 独立查看。
class AwaitReader {
output: TextBlock
status: TextBlock
// workflow 句柄由 ui.spawn 返回,用于观察协作函数状态和最终返回值。
task: Object
// provider 句柄由 ui.readText 返回,apply 的 await 等待它;两个字段不是同一个 Task 的别名。
file: Object
response: String
// await 在文件未完成时挂起并保留 self/操作数;恢复后只执行后半段一次,再把字符串作为 workflow.result。
function apply(self: AwaitReader): String {
// 调度器启动 apply 后遇到未完成 file 会保留续体,后续 provider 就绪再恢复;成功结果才赋给 response。
self.response = await self.file
self.output.text = "读取完成;在 REPL 查看 reader.response 或 reader.task.result()"
// 正常返回值成为 workflow.result(),与 file 的读取结果来源相同但属于另一个任务结果。
return self.response
}
// 先创建读任务,再调度普通函数 apply;spawn 而非新 async 语法提供可暂停执行上下文。
function read(self: AwaitReader, path: String): Unit {
// 先安装本轮文件任务,省略成功回调;它以可 await 的结果状态通知 workflow。
self.file = ui.readText(self, "file", path)
// 再安装 workflow,捕获的是绑定 self 的方法;spawn 安排稍后执行,不在这一赋值处同步跑完 apply。
self.task = ui.spawn(self, "workflow", self.apply)
// 启动后清上次业务结果及显示提示,新的 await 恢复后才写入本轮文本。
self.response = ""
self.output.text = "等待文件"
// 显示的是 workflow 状态,等待 provider 时它仍报告 running;结束后 result 可从 Task 或 response 读取。
self.status.bind("text", self.task.status)
}
}
output = TextBlock("在 REPL 调用 reader.read(绝对路径字符串)")
// 只展示协作 workflow 的状态,provider 自身状态可从 reader.file 单独查询。
status = TextBlock("")
// 占位值只用于满足初始字段构造;在 read 内被真实 Task 替换,页面建立不自动读文件。
reader = AwaitReader(output,status,ui.state(0),ui.state(0),"")
// 页面只投影 status/output,两个任务 owner 都是 reader,页面可见与否不是该普通 owner 的交付资格条件。
page = Page()
page.title = "await 文件"
page.render(Column(24,16,status,output))