40 lines
2.9 KiB
Plaintext
40 lines
2.9 KiB
Plaintext
// 异步 UTF-8 文件读取:在 Console 调用 reader.read(绝对路径),后台 provider 只交付文本,VM worker 执行业务回调。
|
||
// owner/key 相同的新读取替换旧任务;provider 读取失败记录 Task.error、不执行 apply;apply 自身失败则遵循共享运行时停域规则。
|
||
// 持有三个显示对象与当前任务;task 初值占位,第一次 read 后替换为真实 Task。
|
||
class FileReader {
|
||
// 这三个字段保存已构造的文字对象引用,回调更新同一业务对象,不创建一份新的页面或复制 Mount。
|
||
output: TextBlock
|
||
problem: TextBlock
|
||
status: TextBlock
|
||
// 初始用通用 Object 占位;read 安装真实 Task 后可查询 status/error,result 需等待成功交付,apply 不会在占位阶段执行。
|
||
task: Object
|
||
// 仅成功时调用,result 在成功回调期间已可读;写原 TextBlock 触发显示刷新。
|
||
function apply(self: FileReader): Unit {
|
||
// 任务调度器在 I/O 成功且仍有交付资格时调用绑定的 apply;self 是原 reader,调用者无需另外传参。
|
||
// 本例适用于不超过 TextBlock 16 KiB UTF-8 字节预算的文件;readText 自身允许至多 1 MiB,读取成功不保证这次控件赋值合法。
|
||
self.output.text = self.task.result()
|
||
}
|
||
// 以 self 为 owner、file 为 key 启动读取,清空旧输出,并把状态/错误文字绑定到当前任务。
|
||
function read(self: FileReader, path: String): Unit {
|
||
// path 是 Console 本次传入的路径;任务创建同步返回句柄,文件读取在后台,方法这里不会等文件内容。
|
||
self.task = ui.readText(self, "file", path, self.apply)
|
||
// 清掉上次显示与当前读取状态对齐;已取消的旧任务不能稍后回写覆盖这次读取。
|
||
self.output.text = ""
|
||
// Task.status/error 是零参数只读方法,可直接作为绑定计算;换任务后绑定也随本次调用更新。
|
||
self.status.bind("text", self.task.status)
|
||
self.problem.bind("text", self.task.error)
|
||
}
|
||
}
|
||
// 先建立界面对象,保持 reader 为可从 Console 操作的全局业务入口。
|
||
output = TextBlock("尚未读取文件")
|
||
// 单独显示 Task.error;失败不会触发 apply,所以读不到新内容时也能通过绑定看到错误。
|
||
problem = TextBlock("")
|
||
// 独立进度控件绑定到这次任务的方法,普通重绘不会重新提交 readText。
|
||
status = TextBlock("")
|
||
// 全局 reader 保留 owner 和三个显示对象;ui.state(0) 仅满足 Object 字段初值,不是文件结果。
|
||
reader = FileReader(output, problem, status, ui.state(0))
|
||
// 页面只是展示输出,任务 owner 是 reader;关闭这个页面不等于直接取消 reader 下的任务。
|
||
page = Page()
|
||
page.title = "异步文件"
|
||
page.render(Column(24,16,TextBlock("在 REPL 调用 reader.read(绝对路径字符串)",2),status,output,problem))
|