山海万灵 HarmonyOS 文化知识实战续篇(17):loading、empty、error、retry 统一状态落地
知识应用启动时读者看到的并不是一个抽象的请求过程而是图鉴、地域和探索进度能否在合适的时刻出现。山海万灵把加载、内容、空态和恢复动作收敛为同一份状态让首页、图鉴、探索、馆长和档案页共享数据变化的语义。一、四种状态比多个布尔值更稳定单独维护 isLoading、isEmpty 和 hasError 容易产生互相矛盾的组合页面既在加载又提示没有内容或者已经回退到本地资料却仍显示错误。统一 phase 只允许一个主状态生效isLocalFallback 则补充内容的来源信息。export type ShanhaiAppDataPhase LOADING | CONTENT | EMPTY | ERROR; export interface ShanhaiAppLoadState { phase: ShanhaiAppDataPhase; message: string; isLocalFallback: boolean; } export function createShanhaiLoadingState(): ShanhaiAppLoadState { return { phase: LOADING, message: 正在同步山海资料请稍候。, isLocalFallback: false }; }这个模型的关键不在于枚举数量而在于页面只消费一个可信结果。内容可用时进入 CONTENT必要资料为空时进入 EMPTY远端与本地都无法提供内容时才进入 ERROR。每个状态都能映射到明确的视觉反馈和下一步动作。二、启动流程先写入 Loading再决定去向启动阶段先让页面进入 LOADING再由 Bootstrap 结果决定后续状态。内容加载和状态写入在同一处完成避免各个 Feature 页面分别猜测数据是否已经准备好。private async refreshBootstrap(): Promisevoid { this.appLoadState createShanhaiLoadingState(); try { const result await this.appViewModel.loadBootstrapWithStatus(); if (!result.hasRequiredContent) { this.appLoadState createShanhaiEmptyState(); return; } this.applyBootstrap(result.bootstrap); this.appLoadState createShanhaiContentState( result.isLocalFallback ? mock-api 暂不可用正在使用本地内容。 : 内容与图谱已同步。, result.isLocalFallback ); this.refreshAiContext(result.bootstrap.beasts[0].id); } catch (_) { this.appLoadState createShanhaiErrorState(); } }这段顺序同时保留了两层信息页面有没有可展示资料以及资料是否来自本地回退。远端请求暂时失败并不等于读者无法继续阅读只要本地资料完整页面仍进入 CONTENT并用提示语说明当前来源。三、空态和错误态承担不同责任状态出现条件页面反馈用户动作LOADING正在读取启动资料显示进度与同步提示等待CONTENT必要资料已经可用展示图鉴与探索内容继续浏览EMPTY启动结果缺少必要内容说明暂无可展示资料重新同步ERROR没有可用内容可以恢复给出恢复提示重试加载EMPTY 表示结果有效但没有可展示内容ERROR 表示无法获得可用内容。把两者合并会让恢复策略变得模糊空态需要重新同步错误态需要重试加载并且提示文字必须让读者知道接下来能够做什么。四、恢复面板只解释状态不复制业务流程统一面板根据 phase 选择标题和按钮文案。它不直接处理网络细节也不复制 Bootstrap 的读取逻辑所有恢复操作都回到 onRetry从而避免不同页面分别实现一套不一致的重试链路。private title(): string { if (this.state.phase LOADING) { return 正在准备山海资料; } if (this.state.phase EMPTY) { return 暂未发现可展示内容; } return 内容加载失败; } private actionText(): string { return this.state.phase EMPTY ? 重新同步 : 重试加载; }当页面进入恢复模式读者看到的是同一套术语和动作。后续如果增加网络状态、缓存更新或内容版本提示只需要扩展状态层的契约Feature 页面仍然通过同一面板获得一致反馈。五、重试入口必须回到同一条启动链路首页、图鉴、探索和馆长页将同一个 appLoadState 传入各自内容组件并把恢复动作回调到 refreshBootstrap。这样一次点击不会只刷新局部卡片而是重新取得完整 Bootstrap 并再计算跨页面共享的数据。ShanhaiHomePageContent({ beasts: this.beasts, discoveredCount: this.discoveredIds.length, passportCount: this.passportRegionIds.length, syncState: this.appLoadState, onRetrySync: () { this.refreshBootstrap(); } })这种入口收敛还能避免并发状态漂移。刷新前先切到 LOADING成功后一次性应用 Bootstrap失败时统一进入 ERROR页面不会在旧数据与新提示之间留下半更新的组合。六、页面证据观察的是恢复动作下图展示空资料状态下的“重新同步”入口。读者可以看到状态面板没有把空内容伪装成正常图鉴也保留了恢复动作。执行重试后应用会重新走 Bootstrap 流程并用内容状态或新的恢复状态替换当前面板。七、回退内容仍然属于 Content远端服务不可用而本地资料仍然完整时页面不会切换到 ERROR。内容、图谱和探索入口保持可用状态消息提示正在使用本地内容。这个取舍把“数据来源暂时变化”和“读者无法继续阅读”分开处理避免把可用的离线资料隐藏在错误页之后。结果主状态isLocalFallback页面行为远端成功CONTENTfalse显示同步完成后的内容远端失败、本地成功CONTENTtrue继续展示本地资料并提示来源必要资料为空EMPTYfalse显示重新同步没有可用资料ERRORtrue显示重试加载八、验收关注状态切换而不是单个控件验收这条链路时应先观察启动时的同步提示再检查内容可用后的一级页面随后进入空资料状态并点击重新同步确认恢复入口回到完整启动流程。验证重点是 phase、提示语和用户动作是否同步变化而不是只确认某个按钮能够被点击。function applyState(state: ShanhaiAppLoadState): string { if (state.phase LOADING) return 显示加载进度; if (state.phase CONTENT state.isLocalFallback) return 显示本地内容提示; if (state.phase CONTENT) return 显示已同步内容; if (state.phase EMPTY) return 显示重新同步入口; return 显示重试加载入口; }九、状态协议为后续功能保留边界统一状态并不要求每个页面拥有相同布局但要求它们对同一份数据结果作出一致解释。未来增加缓存刷新、内容版本或更细粒度的局部加载时可以在状态层增加字段或子状态而不让五个页面各自引入新的布尔值组合。状态模型、恢复入口和页面回读共同形成了一条可维护的加载链路。HarmonyOS 的状态管理机制可参考 ArkTS 状态管理官方概览。十、把状态更新视为一次完整提交加载链路还要处理快速重复触发。读者连续点击“重新同步”时旧请求可能晚于新请求返回如果旧结果直接覆盖页面就会把已经恢复的内容重新写回空态。状态协调层应为每次启动请求维护递增序号只接受仍然是最新序号的结果。这样 Loading、Content 和恢复面板始终对应同一次请求而不会因返回顺序随机变化。对本地回退也应采用同样的提交原则。先确认远端结果是否仍属于当前请求再决定是否采用本地内容本地内容一旦被选中就连同 isLocalFallback 和提示语一起写入状态。页面只在完整状态对象到达后重新渲染避免列表已经替换而顶部提示仍停留在旧请求的信息。private bootstrapSequence: number 0; private async refreshWithSequence(): Promisevoid { const sequence this.bootstrapSequence; this.appLoadState createShanhaiLoadingState(); try { const result await this.appViewModel.loadBootstrapWithStatus(); if (sequence ! this.bootstrapSequence) return; if (!result.hasRequiredContent) { this.appLoadState createShanhaiEmptyState(); return; } this.applyBootstrap(result.bootstrap); this.appLoadState createShanhaiContentState( result.isLocalFallback ? 正在使用本地内容。 : 内容与图谱已同步。, result.isLocalFallback ); } catch (_) { if (sequence this.bootstrapSequence) this.appLoadState createShanhaiErrorState(); } }这里的序号不是为了给请求编号展示给读者而是为了保护界面事实较早请求只能在它仍然最新时提交结果。网络慢、切换页面或重复点击都不会让旧回调覆盖当前状态。若页面已经卸载协调层也可以在生命周期结束时递增序号使未完成请求自然失效。状态消息同样需要在一次提交中更新。成功内容、空态说明和恢复按钮的文案不应分别异步写入它们属于一个对外可观察的状态快照。读者在任何时刻看到的标题、提示和动作都来自同一个 phase这也是排查加载问题时最容易复现、最容易回读的边界。当后续接入缓存刷新时可以把“正在显示旧内容并刷新”表示为 CONTENT 下的附加字段而不是重新引入多个互斥布尔值。页面继续展示当前图鉴提示区显示刷新进度只有缓存与网络内容都不可用时才转入恢复面板。这样既不会遮蔽可阅读内容也能让失败路径保持明确。

相关新闻

KKCE: 基于边缘计算脚本注入的网站测速逻辑劫持与合规审计-快快测

KKCE: 基于边缘计算脚本注入的网站测速逻辑劫持与合规审计-快快测

一、引言:为什么源代码干净,网站测速却显示"多余"的请求? 在前端安全领域,开发者习惯于通过本地构建检查(npm audit)和服务器端文件完整性校验来确保代码安全。只要本地 dist 目录下的 app.js 哈…

2026/10/15 5:30:26 阅读更多 →
李飞飞团队全新统一世界模型:15小时数据兼顾正向仿真、逆向动作生成

李飞飞团队全新统一世界模型:15小时数据兼顾正向仿真、逆向动作生成

一站式支撑机器人策略评估、模型规划与动作提取三大具身任务。 ——统一世界建模 目录 01 掩码视觉动作完整技术实现逻辑 掩码动作:把动作直接“画”进视频画面 两类互补掩码数据集构建方案 轻量化LoRA微调方案,无全量重训开销 三大下游标准化…

2026/10/15 5:41:42 阅读更多 →
企业级Git分支管理策略——从Git Flow到团队协作规范

企业级Git分支管理策略——从Git Flow到团队协作规范

一、为什么需要分支管理策略?在现代软件开发中,版本控制是团队协作的核心。Git提供了强大的分支管理能力,但如果没有明确的分支策略,团队很容易陷入:混乱的提交历史频繁的代码冲突不可预测的发布流程紧急Bug无法快速响…

2026/10/6 11:24:31 阅读更多 →

最新新闻

AI魔改与AIGC短剧合规指南:红线、审核与实操清单

AI魔改与AIGC短剧合规指南:红线、审核与实操清单

我最近频繁收到做内容的朋友私信,问得最多的就是一句话:AI魔改还能不能做?AI生成的短剧发出去会不会被限流?甚至有人直接甩过来一个通知截图,内容是“该作品因涉及AI生成内容未标注,已限制推荐”。说实话&a…

2026/10/15 5:41:36 阅读更多 →
软件测试四个阶段详解:单元、集成、系统、验收一次讲透

软件测试四个阶段详解:单元、集成、系统、验收一次讲透

刚带团队的时候,我最喜欢问面试者一个问题:“软件测试分几个阶段?”十个人里有八个会回答“单元、集成、系统、验收”,但你再追问一句“为什么这么分?每个阶段的入口和出口标准是什么?”能答清楚的人立刻少…

2026/10/15 5:41:36 阅读更多 →
51单片机温度计实战:DS18B20时序+数码管扫描+EEPROM报警系统

51单片机温度计实战:DS18B20时序+数码管扫描+EEPROM报警系统

简介:本资源是一份面向电子信息工程专业本科生的51单片机课程设计完整文档,聚焦数字温度计系统开发,解决嵌入式基础项目从原理设计、硬件搭建到软件调试的全流程实践问题。文档详述以AT89C51为核心控制器,集成DS18B20单总线温度传…

2026/10/15 5:41:36 阅读更多 →
Redis核心数据结构精讲:从String到Zset的选型与排行榜实战

Redis核心数据结构精讲:从String到Zset的选型与排行榜实战

先说说我为什么想写这篇东西。我见过太多人一开始玩 Redis,把命令背得滚瓜烂熟,SET、GET、LPUSH、SADD 张口就来,可真到业务里要做选型的时候,犹豫了:用户信息到底放 String 还是 Hash?消息队列能不能直接用…

2026/10/15 5:41:36 阅读更多 →
分布式事务设计实战:从最终一致性到七步落地法

分布式事务设计实战:从最终一致性到七步落地法

1. 为什么“分布式事务”不是加个注解就能解决的事“24.分布式事务设计”这个标题,乍看像教科书目录里一个平平无奇的章节编号,但凡在真实系统里踩过坑的人,看到它第一反应不是翻页,而是下意识摸了摸键盘右上角的Esc键——因为过去…

2026/10/15 5:41:36 阅读更多 →
Spring Boot 3迁移MyBatis-Plus:SqlSessionFactory缺失根因与修复

Spring Boot 3迁移MyBatis-Plus:SqlSessionFactory缺失根因与修复

前段时间把一个老服务从Spring Boot 2.7往3.2迁移,顺手把MyBatis也换成MyBatis-Plus,结果启动直接抛了一串异常,核心信息就是Error creating bean with name sqlSessionFactory。但更让人头疼的是,控制台给的提示并不统一——有时…

2026/10/15 5:40:35 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →