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

能否通过函数调用或按钮点击初始化resource与rxResource?

问题原因

错误NG0203明确指出:rxResource()仅能在Angular的注入上下文(如构造函数、工厂函数、字段初始化器,或通过runInInjectionContext包裹的函数)内调用。而按钮点击触发的getUsers方法不在该上下文范围内,直接调用rxResource()会触发此错误。

解决方案

方案一:提前初始化rxResource,按需触发加载

在组件的注入上下文(字段初始化或构造函数)中创建rxResource实例,关闭自动加载,然后在按钮点击时调用reload()触发数据请求。

修改后的TS代码:

import { inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { rxResource, resource, ResourceStatus, ResourceRef } from '@angular/core/rxjs-interop';
import { map } from 'rxjs';

rs = ResourceStatus;
http = inject(HttpClient);
resource!: ResourceRef<any>;
// 提前在注入上下文内初始化rxResource,关闭自动加载
rxResource = rxResource({
  loader: () => {
    return this.http
      .get(`https://jsonplaceholder.typicode.com/todos`)
      .pipe(map((data: any) => data.slice(0, 10)));
  },
  autoLoad: false
});

getUsers() {
  // 触发数据加载
  this.rxResource.reload();
  
  this.resource = resource({
    loader: () => {
      return fetch(`https://jsonplaceholder.typicode.com/todos/`)
        .then((res: any) => res.json())
        .then((res: any) => res.slice(0, 10));
    },
  });
}

reset() {
  this.rxResource?.reset();
  this.resource?.reset();
}

方案二:用runInInjectionContext包裹rxResource调用

若需在按钮点击时才创建rxResource实例,可注入Injector,通过runInInjectionContext手动提供注入上下文,包裹rxResource的调用逻辑。

修改后的TS代码:

import { inject, Injector, runInInjectionContext } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { rxResource, resource, ResourceStatus, ResourceRef } from '@angular/core/rxjs-interop';
import { map } from 'rxjs';

rs = ResourceStatus;
http = inject(HttpClient);
injector = inject(Injector);
resource!: ResourceRef<any>;
rxResource!: ResourceRef<any>;

getUsers() {
  // 手动注入上下文,包裹rxResource调用
  runInInjectionContext(this.injector, () => {
    this.rxResource = rxResource({
      loader: () => {
        return this.http
          .get(`https://jsonplaceholder.typicode.com/todos`)
          .pipe(map((data: any) => data.slice(0, 10)));
      },
    });
  });
  
  this.resource = resource({
    loader: () => {
      return fetch(`https://jsonplaceholder.typicode.com/todos/`)
        .then((res: any) => res.json())
        .then((res: any) => res.slice(0, 10));
    },
  });
}

reset() {
  this.rxResource?.reset();
  this.resource?.reset();
}
原问题代码参考

HTML代码

@if(rxResource) {
  @if(![rs.Loading, rs.Reloading].includes(rxResource.status())) {
    {{rxResource.value() | json}}
  } @else{
    Loading...
  }
}
@if(resource) {
  @if(![rs.Loading, rs.Reloading].includes(resource.status())) {
    {{resource.value() | json}}
  } @else{
    Loading...
  }
}
<button (click)="getUsers()">Get Users</button>
<button (click)="reset()">Reset</button>

TS代码

rs = ResourceStatus;
http = inject(HttpClient);
resource!: ResourceRef<any>;
rxResource!: ResourceRef<any>;

getUsers() {
  this.rxResource = rxResource({
    loader: () => {
      return this.http
        .get(`https://jsonplaceholder.typicode.com/todos`)
        .pipe(map((data: any) => data.slice(0, 10)));
    },
  });
  this.resource = resource({
    loader: () => {
      return fetch(`https://jsonplaceholder.typicode.com/todos/`)
        .then((res: any) => res.json())
        .then((res: any) => {
          return res.slice(0, 10);
        });
    },
  });
}

内容的提问来源于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 08:48:13