渐进式编程课
鸿蒙 目录
第 17 课2026.07.27

适用场景:页面进入后请求网络数据、读取数据库或执行其他需要等待的任务

第 17 课:异步数据加载与页面状态

  • 日期:2026-07-27
  • 知识点:async / await、加载状态、成功结果与错误信息
  • 适用场景:页面进入后请求网络数据、读取数据库或执行其他需要等待的任务

承接上一课的组件生命周期:上一课确定了“何时开始加载”;本课继续学习“异步任务完成后,如何用明确的数据状态驱动页面”。

1. 核心概念:用状态表达加载结果

异步加载通常有三种结果:

text
开始加载 -> loading = true
加载成功 -> 写入数据
加载失败 -> 写入错误信息
任务结束 -> loading = false

async 函数会返回 Promise,await 用来等待异步结果。页面只根据 loading、items 和 errorMessage 渲染,不在 UI 层伪造加载结果。

2. 最小示例

ts
@Entry
@Component
struct MessagePage {
  @State loading: boolean = false;
  @State items: string[] = [];
  @State errorMessage: string = '';

  aboutToAppear(): void {
    this.loadMessages();
  }

  async loadMessages(): Promise<void> {
    this.loading = true;
    this.errorMessage = '';

    try {
      this.items = await this.queryMessages();
    } catch (error) {
      this.errorMessage = '加载失败,请重试';
    } finally {
      this.loading = false;
    }
  }

  queryMessages(): Promise<string[]> {
    return Promise.resolve(['系统通知', '学习提醒']);
  }

  build() {
    Column({ space: 12 }) {
      if (this.loading) {
        Text('加载中...')
      } else if (this.errorMessage.length > 0) {
        Text(this.errorMessage)
          .fontColor(Color.Red)
      } else {
        ForEach(this.items, (item: string) => {
          Text(item)
        }, (item: string) => item)
      }
    }
    .width('100%')
    .padding(20)
  }
}

try 处理成功结果,catch 记录失败结果,finally 保证无论成功还是失败都会结束加载状态。实际项目中,把 queryMessages() 替换为真实的数据层调用即可。

3~5 分钟练习

给示例增加一个“重新加载”按钮:

  1. 点击按钮时再次调用 loadMessages()。
  2. 正在加载时禁用按钮。
  3. 按钮文字在加载时显示“加载中”,其余时间显示“重新加载”。

参考答案

在 build() 的 Column 中追加:

ts
Button(this.loading ? '加载中' : '重新加载')
  .enabled(!this.loading)
  .onClick(() => {
    this.loadMessages();
  })

按钮只触发数据加载;是否可点击和显示什么文字,都直接由 loading 状态决定。

与上一课的联系

上一课使用 aboutToAppear() 确定组件进入时启动任务,并强调离开时释放长期资源;本课把一次异步数据加载接到这个生命周期点上,再用明确的加载、成功和失败状态驱动 UI。下一步可以继续学习如何把页面请求逻辑下沉到独立的数据服务中。