从端到云:用 ArkTS + Serverless 跑通鸿蒙待办清单的端云协同

举报
yd_227460417 发表于 2026/11/05 01:36:10 2026/11/05
【摘要】 本文以「云同步待办清单」为例,梳理 HarmonyOS 端侧 ArkTS 与华为云 Serverless 后端的协作方式,覆盖登录态、数据同步、离线补偿和部署联调几个关键环节,适合已经掌握 ArkUI 基础、准备把应用从“单机”推进到“端云一体”的开发者。 一、为什么要把待办清单做成端云协同纯端侧待办应用实现成本很低,但一旦换设备,数据就断了。端云协同要解决的核心问题其实只有三个:身份:同一...

本文以「云同步待办清单」为例,梳理 HarmonyOS 端侧 ArkTS 与华为云 Serverless 后端的协作方式,覆盖登录态、数据同步、离线补偿和部署联调几个关键环节,适合已经掌握 ArkUI 基础、准备把应用从“单机”推进到“端云一体”的开发者。

一、为什么要把待办清单做成端云协同

纯端侧待办应用实现成本很低,但一旦换设备,数据就断了。端云协同要解决的核心问题其实只有三个:

  1. 身份:同一用户在手机、平板、模拟器上看到同一份数据;
  2. 一致性:新增、修改、删除操作要能可靠落到云端,并在多端之间同步;
  3. 弱网可用:断网时仍能记录,恢复网络后自动补偿。

把这三件事拆开,端侧负责交互和本地缓存,云侧负责鉴权、持久化和并发控制,职责就清晰了。

二、整体架构

一个够用且不过度设计的架构如下:

ArkTS / ArkUI 端侧
  ├─ 登录页         → 获取并保存会话 Token
  ├─ 任务列表页     → 本地缓存 + 云端拉取
  └─ 同步模块       → 轮询 / 手动刷新 / 失败重试

华为云 Serverless 云侧
  ├─ APIG           → 统一入口、鉴权、限流
  ├─ FunctionGraph  → 登录、任务增删改查等云函数
  └─ RDS MySQL      → users / sessions / tasks 三张表

端侧不直接连数据库,所有请求都经过 APIG;云函数保持无状态,会话信息落库,便于水平扩容。

三、端侧:先把登录态管好

端云协同里最容易返工的地方不是接口,而是登录态。建议在应用启动时做一次会话恢复:

// SessionManager.ets
import preferences from '@ohos.data.preferences';

export class SessionManager {
  private static store: preferences.Preferences | null = null;

  static async init(context: Context): Promise<void> {
    this.store = await preferences.getPreferences(context, 'session');
  }

  static async saveToken(token: string, expireAt: number): Promise<void> {
    await this.store?.put('token', token);
    await this.store?.put('expireAt', expireAt);
    await this.store?.flush();
  }

  static async getValidToken(): Promise<string | null> {
    const token = await this.store?.get('token', '') as string;
    const expireAt = await this.store?.get('expireAt', 0) as number;
    if (!token || Date.now() >= expireAt) {
      return null;
    }
    return token;
  }
}

几个实践建议:

  • Token 不要只放内存,进程被杀后会丢失;
  • 过期时间留出 5 分钟余量,避免请求发出时刚好过期;
  • 收到 401 时统一清理本地会话并跳转登录页,不要在多个页面各写一套。

四、端侧:列表与同步

任务列表采用“本地缓存优先、云端增量覆盖”的策略。首屏先读本地数据,保证秒开;随后异步拉取云端最新数据。

interface TodoItem {
  id: string;
  title: string;
  priority: number;
  dueAt: number;
  updatedAt: number;
  deleted: boolean;
}

async function pullTasks(since: number): Promise<TodoItem[]> {
  const token = await SessionManager.getValidToken();
  if (!token) {
    throw new Error('SESSION_EXPIRED');
  }
  const resp = await http.createHttp().request(
    `${BASE_URL}/tasks?since=${since}`,
    {
      method: http.RequestMethod.GET,
      header: { Authorization: `Bearer ${token}` }
    }
  );
  return JSON.parse(resp.result as string).items as TodoItem[];
}

同步策略可以分阶段演进:

  1. 第一版:进入前台时全量拉取,实现简单;
  2. 第二版:用 updatedAt 做增量拉取,减少流量;
  3. 第三版:本地维护待同步队列,弱网时先写本地、联网后按顺序补传。

删除建议使用软删除(deleted 标记),否则多端并发时很容易出现“A 端删了、B 端又把它推回来”的问题。

五、云侧:三张表撑起最小闭环

最小可用的数据模型:

CREATE TABLE users (
  id          VARCHAR(32) PRIMARY KEY,
  phone       VARCHAR(20) UNIQUE NOT NULL,
  created_at  BIGINT NOT NULL
);

CREATE TABLE sessions (
  token       VARCHAR(64) PRIMARY KEY,
  user_id     VARCHAR(32) NOT NULL,
  expire_at   BIGINT NOT NULL,
  INDEX idx_user (user_id)
);

CREATE TABLE tasks (
  id          VARCHAR(32) PRIMARY KEY,
  user_id     VARCHAR(32) NOT NULL,
  title       VARCHAR(200) NOT NULL,
  priority    TINYINT DEFAULT 0,
  due_at      BIGINT DEFAULT 0,
  updated_at  BIGINT NOT NULL,
  deleted     TINYINT DEFAULT 0,
  INDEX idx_user_updated (user_id, updated_at)
);

云函数侧要注意两件事:

  • 所有查询必须带 user_id 条件,不要只按 task_id 查询后再在代码里判断归属;
  • 写操作使用 updated_at 做乐观并发控制,更新时带上旧版本号,避免后写覆盖先写。

六、部署与联调清单

在华为云上部署时,建议按下面的顺序验收,能少走很多弯路:

  1. RDS 白名单确认已放通 FunctionGraph 所在网段;
  2. APIG 的路由、超时时间和 CORS 配置逐项核对;
  3. 云函数环境变量中的数据库连接串不要硬编码在代码里;
  4. 用 curl 先跑通登录、创建、查询、删除四条链路,再接端侧;
  5. 端侧真机与模拟器分别验证一次弱网和断网恢复。

七、几个容易踩的坑

  • 时间戳统一用毫秒:端侧 Date.now() 与数据库字段类型要对齐,避免秒/毫秒混用;
  • 轮询不是越多越好:30 秒轮询适合演示,正式产品建议结合页面生命周期,退到后台就停止;
  • 错误码要可区分:网络失败、会话过期、业务校验失败要分开处理,否则用户只会看到“加载失败”;
  • 不要在前端存数据库凭证:端侧只持有短期 Token,数据库账号只存在于云函数环境变量中。

八、小结

端云协同的难点从来不是“把接口调通”,而是登录态、数据一致性和弱网补偿这三件事能不能形成闭环。先把会话和软删除做扎实,再逐步引入增量同步和离线队列,应用的可维护性会好很多。

如果你的目标是快速验证,建议先从一张 tasks 表、四个接口(登录、列表、创建、删除)开始,跑通之后再扩展优先级、截止时间和多端同步。小闭环跑顺了,后面的功能才有稳定的地基。

【标签】

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。