You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular组件如何仅在IndexedDB表数据填充完成后加载数据

问题根因
  • 城市数据同步流程(请求API、批量写入IndexedDB)全为异步操作,没有对外暴露执行完成的状态
  • 组件初始化时直接调用getData读库,此时写入操作还未执行完成,自然拿到空数据
  • 原有的写入方法没有返回Promise,外层无法感知写入任务的完成状态,没办法做批量等待
  • 代码存在笔误:你调用的addCityToIndexedDb方法实际定义的名称是addCitiesToIndexedDb,注意修正命名避免报错
优化方案

第一步:修改Service层,增加同步状态监听

首先调整Service的代码,补全异步状态通知逻辑:

import { BehaviorSubject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class MyService {
  // 新增:记录城市同步完成状态的Subject,初始值为false
  private citiesSyncDone$ = new BehaviorSubject<boolean>(false);
  // 对外暴露只读的可观察对象,避免外部直接修改状态
  public citiesSyncDoneObservable$ = this.citiesSyncDone$.asObservable();

  synchronizeCitiesOnLogin() {
    this.getCitiesFromApi().subscribe({
      next: async (cities) => {
        // 生成所有写入任务的Promise数组
        const writePromises = cities.map(city => this.addCityToIndexedDb(city));
        // 等待所有写入操作全部完成
        await Promise.all(writePromises);
        // 更新同步完成状态
        this.citiesSyncDone$.next(true);
      },
      error: (err) => {
        console.error('同步城市数据失败', err);
        // 可根据业务需求处理失败逻辑,比如复用旧缓存、提示用户等
      }
    });
  }

  // 修改:让写入方法返回Promise,外层可感知完成状态
  addCityToIndexedDb(city): Promise<void> {
    return this.cityTable
      .add(city)
      .catch(e => {
        alert('Error: ' + (e.stack || e));
        // 单个写入失败不中断整体流程的话,这里返回resolve即可
        return Promise.resolve();
      });
  }

  // 修改: getData自动等待同步完成后再返回数据
  async getData(): Promise<any> {
    // 同步已完成,直接返回本地数据
    if (this.citiesSyncDone$.value) {
      return this.getDataFromIndexedDb();
    }
    // 同步未完成,等待完成通知后再读库返回
    return new Promise((resolve) => {
      const subscription = this.citiesSyncDoneObservable$.subscribe(done => {
        if (done) {
          this.getDataFromIndexedDb().then(data => resolve(data));
          subscription.unsubscribe();
        }
      });
    });
  }

  // 其余原有方法(getCitiesFromApi、getDataFromIndexedDb)不用改
  ......
}

第二步:组件层逻辑(基本不用改,可选增加加载状态)

组件的调用逻辑不用调整,也不需要加setTimeout,可选增加加载状态提升用户体验:

ngOnInit() {
  // 可选:展示加载状态
  this.loading = true;
  this.myService.getData().then(data => {
    this.worldCities = data;
    this.loading = false;
  });
}
可选优化点
  • 如果需要更快的首次加载速度,可以在拿到API返回的cities时先缓存一份到Service的内存变量中,getData时如果同步未完成直接返回内存中的数据,不用等写库完成,后台异步执行写库操作即可
  • 可增加同步超时逻辑,避免流程卡住无响应
  • 不是每次登录都需要全量同步的话,可以增加数据版本判断,本地数据已经是最新版本时直接读本地,跳过接口请求和写库流程,大幅提升加载速度

内容的提问来源于stack exchange,提问作者godzo101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 19:09:03