You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何优化Angular(使用最新Signals和rxResource)的请求流程?避免重复调用expList接口并按需触发getstrategy

如何优化Angular(使用最新Signals和rxResource)的请求流程?避免重复调用expList接口并按需触发getstrategy

我来帮你梳理下这个问题的解决方案,你的核心诉求是避免重复请求expList接口,只在页面首次加载、lastLoadedScript变化时才走「expList→getstrategy」流程,后续切换到期日时直接调用getstrategy对吧?咱们可以通过Angular Signal缓存expiryList+重构rxResource逻辑来完美匹配你的需求,具体实现如下:

核心思路

  1. 用Angular Signal缓存expiryList,确保只在必要场景(页面首次加载、脚本切换)请求getExplist
  2. myResourcegetstrategy请求依赖缓存的expiryList,只有缓存为空时才先拉取expList
  3. 监听lastLoadedScript变化,自动清空缓存的expiryList,确保切换脚本时重新触发完整请求链
  4. 后续切换到期日时,直接调用myResource.reload(),复用缓存的expiryList发起getstrategy请求

重构后的代码实现

1. 定义缓存expiryList的Signals和加载状态

import { signal, effect, of, tap, catchError, Observable } from '@angular/core';
import { rxResource } from 'rx-resource'; // 适配你使用的rx-resource库

// 私有信号:缓存expiryList,外部仅能只读访问
private readonly _expiryList = signal<ExpiryDetails[]>([]);
public readonly expiryList = this._expiryList.asReadonly();
// 标记expiryList是否正在加载,用于页面loading状态控制
private readonly _isExpiryListLoading = signal(false);
public readonly isExpiryListLoading = this._isExpiryListLoading.asReadonly();

public expirySortname: string[] = [];

2. 封装带缓存逻辑的expiryList加载方法

private loadExpiryList(script: any): Observable<ExpiryDetails[]> {
  // 如果已有缓存,直接返回缓存数据的Observable
  if (this._expiryList().length > 0) {
    return of(this._expiryList());
  }

  this._isExpiryListLoading.set(true);
  return this.myService.getExplist().pipe(
    tap((expiryDetails: ExpiryDetails[]) => {
      this._expiryList.set(expiryDetails);
      this.expirySortname = expiryDetails.map(e => e.sortname);
      this._isExpiryListLoading.set(false);
    }),
    catchError(err => {
      this._isExpiryListLoading.set(false);
      throw err; // 抛出错误让上层处理
    })
  );
}

3. 监听lastLoadedScript变化,自动清空缓存

在组件构造函数中添加effect,确保切换脚本时重新拉取expList

constructor(private stateService: StateService, private myService: MyService) {
  // 当lastLoadedScript变化时,清空expiryList缓存,触发完整请求链
  effect(() => {
    const currentScript = this.stateService.lastLoadedScript();
    if (currentScript) {
      this._expiryList.set([]); // 清空缓存,下次请求会重新拉取expList
    }
  });
}

4. 重构myResource核心逻辑

myResource = rxResource<{ [key: string]: strategy[] }, { expiryIndex: number }>({
  request: () => {
    // 每次请求携带当前选中的到期日索引
    return { expiryIndex: this.prebuiltExpiry() };
  },
  loader: ({ request }) => {
    const currentScript = this.stateService.lastLoadedScript();
    
    // 先获取expiryList(缓存或新请求),再发起getstrategy请求
    return this.loadExpiryList(currentScript).pipe(
      switchMap(() => {
        // 构造getstrategy请求参数,复用缓存的expiryList
        const tempObj = {
          "StrategyName": "*",
          "Symbol": currentScript.name,
          "ExpiryJulian": this.expiryList()[request.expiryIndex].expiry
        };

        // 发起getstrategy请求并处理响应
        return this.myService.getstrategy(tempObj).pipe(
          map(resp => {
            if (resp['status'] !== 'success') {
              throw new Error('Invalid response from getstrategy');
            }
            return processData(resp['data']); // 适配你的数据处理函数
          })
        );
      })
    );
  }
});

需求匹配验证

  1. 页面首次加载expiryList为空,自动触发getExplist,拿到结果后立即调用getstrategy
  2. 切换到期日:直接调用myResource.reload(),此时expiryList已有缓存,会直接用缓存数据发起getstrategy,不会重复请求expList
  3. 切换脚本(lastLoadedScript变化):effect自动清空expiryList缓存,myResource会重新走「getExplist→getstrategy」完整流程

额外优化建议

  • 如果不同脚本对应的expiryList不同,可以在loadExpiryList中加入脚本标识校验,避免缓存串用
  • 可以给myResource添加请求防抖,防止频繁切换到期日时发起过多请求

备注:内容来源于stack exchange,提问作者Nikunj Guna

火山引擎 最新活动