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

Angular 19+中如何使用Signals在重新计算时缓存查询结果?

Angular 19+中如何使用Signals在重新计算时缓存查询结果?

我完全懂你现在的需求:基于组件状态动态生成一批查询,希望这些查询的结果能被智能缓存——只有第一次遇到这个查询时才发起请求,之后不管组件状态怎么变导致查询列表重新计算,只要是同一个查询就直接用缓存好的结果,还得支持用户手动刷新对吧?

在Angular 19+里,结合Signals和rxResource(或者新出的resource API)来实现这个需求特别顺手,我给你两个实用的落地方案:

方案一:自定义缓存Map+计算信号,完全掌控缓存逻辑

先搞一个全局的缓存Map来存每个查询的结果,再用计算信号判断什么时候该发起请求:

import { computed, signal, inject } from '@angular/core';
import { ResourceService, rxResource } from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-query-list',
  standalone: true,
  template: `
    <div *ngFor="let query of queries()">
      <div *ngIf="getQueryResult(query) as result">
        @if (result.loading) {
          加载中...
        } @else {
          {{ result.data }}
          <button (click)="refreshQuery(query)">刷新结果</button>
        }
      </div>
    </div>
  `
})
export class QueryListComponent {
  // 组件状态信号,用来动态生成查询条件
  componentState = signal({ filter: 'active', page: 1 });
  
  // 根据状态生成查询列表的计算信号
  queries = computed(() => {
    const state = this.componentState();
    // 这里根据你的业务逻辑生成具体查询数组,比如不同参数组合
    return [
      { endpoint: '/api/data', params: { type: 'A', ...state } },
      { endpoint: '/api/data', params: { type: 'B', ...state } }
    ];
  });

  // 缓存Map,用查询的唯一标识当key
  private queryCache = new Map<string, any>();
  private resourceService = inject(ResourceService);

  // 获取单个查询结果的计算信号
  getQueryResult = computed((query) => {
    // 生成唯一缓存key,比如把endpoint和参数转成字符串
    const cacheKey = JSON.stringify(query);
    
    // 缓存存在就直接返回
    if (this.queryCache.has(cacheKey)) {
      return { data: this.queryCache.get(cacheKey), loading: false, isCached: true };
    }

    // 没缓存就发起请求
    const resource = rxResource({
      source: () => this.resourceService.get(query.endpoint, { params: query.params }),
      initialValue: { data: null, loading: true }
    });

    // 请求完成后更新缓存
    resource.value.subscribe({
      next: (data) => {
        this.queryCache.set(cacheKey, data);
      }
    });

    return { data: resource.value(), loading: false, isCached: false };
  });

  // 手动刷新指定查询的方法
  refreshQuery(query: any) {
    const cacheKey = JSON.stringify(query);
    this.queryCache.delete(cacheKey);
    // 触发计算信号重新计算,重新发起请求
    this.queries.set(this.queries());
  }
}

这个方案的好处是逻辑完全可控,你可以随便调整缓存的过期、清理规则。需要注意的是,生成cacheKey时要确保唯一性,避免不同查询被误判成同一个。

方案二:利用resource API内置缓存,简洁省心

Angular 19+的resource API本身就带了缓存能力,只要简单配置就能实现需求:

import { computed, signal, inject } from '@angular/core';
import { resource, ResourceService } from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-query-list',
  standalone: true,
  template: `
    <div *ngFor="let query of queries()">
      <div>
        @if (getQueryResource(query).loading) {
          加载中...
        } @else {
          {{ getQueryResource(query()).data }}
          <button (click)="getQueryResource(query).refresh()">刷新</button>
        }
      </div>
    </div>
  `
})
export class QueryListComponent {
  componentState = signal({ filter: 'active', page: 1 });
  
  queries = computed(() => {
    const state = this.componentState();
    return [
      { uniqueId: 'query-type-A', endpoint: '/api/data', params: { type: 'A', ...state } },
      { uniqueId: 'query-type-B', endpoint: '/api/data', params: { type: 'B', ...state } }
    ];
  });

  private resourceService = inject(ResourceService);

  // 为每个查询创建带缓存的resource
  getQueryResource = computed((query) => {
    return resource({
      source: () => this.resourceService.get(query.endpoint, { params: query.params }),
      initialValue: null,
      // 配置缓存:用查询的唯一ID当缓存key,默认永久有效
      cache: {
        key: query.uniqueId,
        // 要是想加过期时间,就加这行:expiresIn: 3600000(1小时)
      }
    });
  });
}

这个方案更简洁,因为resource已经帮你封装了缓存逻辑,连手动刷新的方法都给你准备好了。核心就是给每个查询分配唯一的uniqueId作为缓存key,只要这个ID不变,就算查询列表重新计算,也会直接复用缓存结果。

几个注意点

  • 如果查询参数很复杂,生成缓存key的时候可以用专门的哈希工具(比如object-hash库),比JSON.stringify更稳定。
  • 要是需要全局共享缓存,可以把缓存Map或者resource的缓存配置放到单独的服务里,这样多个组件能共用同一份缓存。
  • 手动刷新时,记得要么清除对应缓存(方案一),要么调用resource的refresh()方法(方案二),才能触发重新请求。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 13:44:30