能否通过函数调用或按钮点击初始化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
相关产品推荐
相关产品推荐

