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

Angular Resource API实现暂停:停止监听信号但保留最后取值

Angular Resource API 暂停功能实现:保留最后值并停止监听信号变化

需求:实现Angular Resource API的暂停功能,停止监听信号变化但保留最后获取的值。当前调用stop时resource.value()会被清空,需要保留该值用于UI展示,仅停止响应request回调中未来的信号变化。

可复现代码

HTML代码

<div>
  <div>
    Resource Request triggers:
  </div>
  <div>
    <input [(ngModel)]="id" type="number"/>
  </div>
</div>
<div>
  @if(![rs.Loading, rs.Reloading].includes(rxResource.status())) {
    {{rxResource.value() | json}}
  } @else{
    Loading...
  }
</div>
<hr/>
<div>
  @if(![rs.Loading, rs.Reloading].includes(resource.status())) {
    {{resource.value() | json}}
  } @else{
    Loading...
  }
</div>
<hr/>
<div>
<div>Current Status: {{rs[resource.status()]}}</div>
<button (click)="start()">Start Listening</button>
<button (click)="pause()">Pause Listening (Retain last value)</button>
<button (click)="stop()">Stop Listening</button>
</div>

TypeScript代码(原始版本)

export class App {
  id = signal(1);
  rs = ResourceStatus;
  http = inject(HttpClient);
  resourceControl = signal(true);
  resourceRequest = (): ResourceRequest | undefined => {
    if (this.resourceControl()) {
      return {
        id: this.id(),
      };
    } else {
      return undefined;
    }
  };
  resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
    request: this.resourceRequest,
    loader: ({ request: { id }, abortSignal }) => {
      return fetch(`https://jsonplaceholder.typicode.com/todos/${id}`, {
        signal: abortSignal,
      }).then((res: any) => res.json());
    },
  });
  rxResource: ResourceRef<any> = rxResource<ResourceRequest | undefined, any>({
    request: this.resourceRequest,
    loader: ({ request: { id } }) => {
      return this.http.get<any>(
        `https://jsonplaceholder.typicode.com/todos/${id}`
      );
    },
  });

  start() {
    this.resourceControl.set(true);
  }

  stop() {
    this.resourceControl.set(false);
  }

  pause() {
    // how to pause the resource and stop listening to future changes but retain the last value
  }
}

解决方案

核心思路:避免通过返回undefined清空资源值,而是通过新增状态控制request回调,暂停时固定返回最后一次有效的请求参数,不再响应id信号的变化。

修改后的TypeScript代码:

export class App {
  id = signal(1);
  rs = ResourceStatus;
  http = inject(HttpClient);
  resourceControl = signal(true);
  isPaused = signal(false);
  lastValidRequest = signal<ResourceRequest | undefined>({ id: 1 });

  resourceRequest = (): ResourceRequest | undefined => {
    // 原stop逻辑:返回undefined清空值
    if (!this.resourceControl()) {
      return undefined;
    }
    // 暂停状态:返回最后一次有效请求,不响应id变化
    if (this.isPaused()) {
      return this.lastValidRequest();
    }
    // 正常监听状态:更新最后一次请求并返回当前id
    const currentRequest = { id: this.id() };
    this.lastValidRequest.set(currentRequest);
    return currentRequest;
  };

  resource: ResourceRef<any> = resource<ResourceRequest | undefined, any>({
    request: this.resourceRequest,
    loader: ({ request: { id }, abortSignal }) => {
      return fetch(`https://jsonplaceholder.typicode.com/todos/${id}`, {
        signal: abortSignal,
      }).then((res: any) => res.json());
    },
  });

  rxResource: ResourceRef<any> = rxResource<ResourceRequest | undefined, any>({
    request: this.resourceRequest,
    loader: ({ request: { id } }) => {
      return this.http.get<any>(
        `https://jsonplaceholder.typicode.com/todos/${id}`
      );
    },
  });

  start() {
    this.resourceControl.set(true);
    this.isPaused.set(false);
  }

  stop() {
    this.resourceControl.set(false);
  }

  pause() {
    this.isPaused.set(true);
  }
}

方案说明

  1. 新增isPaused信号控制暂停状态,lastValidRequest存储最后一次有效的请求参数
  2. 修改resourceRequest回调:
    • 当处于暂停状态时,返回lastValidRequest的值,不再跟随id信号变化
    • 正常监听时,更新lastValidRequest并返回当前请求参数
  3. start方法重置暂停状态,恢复监听id变化
  4. pause方法仅切换暂停状态,不会清空已获取的资源值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:04:51