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

在Angular中使用@ngneat/query信号时遇NG0203错误求解决

解决Angular中@ngneat/query与信号集成的NG0203错误

错误原因

你触发的NG0203错误,本质是queryResultSignal()(QueryObserver.result()内部调用的方法)必须在Angular的注入上下文(如构造函数、字段初始化器、runInInjectionContext包裹的函数)中执行,但computed的回调函数运行时并不在这个上下文范围内。你在computed里直接调用this.getProduct(...).result(),就违反了这个限制。

解决方案

这里提供两种可行的修复方式:

方案1:用runInInjectionContext包裹信号创建逻辑

通过注入Injector,将result()的调用包裹在runInInjectionContext中,确保它在合法的注入上下文里执行:

  1. 导入所需依赖:
import { Component, computed, inject, Injector, runInInjectionContext } from '@angular/core';
  1. 修改ProductComponent代码:
export class ProductComponent {
  query = injectQuery();
  injector = inject(Injector); // 注入Injector实例
  productId = toSignal(
    inject(ActivatedRoute).params.pipe(map((params) => Number(params['id'])))
  );

  product = computed(() => {
    const productQuery = this.getProduct(this.productId()!);
    // 用runInInjectionContext包裹result()调用,确保注入上下文合法
    return runInInjectionContext(this.injector, () => productQuery.result());
  });

  getProduct(id: number) {
    return this.query({
      queryKey: ['product', id],
      queryFn: () => of({ id }).pipe(delay(2 * 1000)),
    });
  }
}

方案2:使用querySignal(推荐)

@ngneat/query提供了querySignal方法,专门为Angular信号场景设计,无需手动处理注入上下文:

  1. 修改getProduct方法,改用querySignal:
getProduct(id: number) {
  return this.query.querySignal({
    queryKey: ['product', id],
    queryFn: () => of({ id }).pipe(delay(2000)),
  });
}
  1. 简化computed逻辑:
product = computed(() => this.getProduct(this.productId()!));
  1. 模板中直接使用信号值(无需额外调用result()):
<ng-container *ngIf="product() as product">
  {{ product.data | json }}
</ng-container>

完整修正后的代码示例(方案2)

import { CommonModule } from '@angular/common';
import { Component, computed, inject } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { ActivatedRoute, RouterModule, provideRouter } from '@angular/router';
import { injectQuery } from '@ngneat/query';
import { delay, map, of } from 'rxjs';
import { toSignal } from '@angular/core/rxjs-interop';

import 'zone.js';

console.clear();

@Component({
  standalone: true,
  selector: 'product',
  imports: [CommonModule],
  template: `
    in product: 
    <ng-container *ngIf="product() as product">
      {{product.data |json}}
    </ng-container>
  `,
})
export class ProductComponent {
  query = injectQuery();
  productId = toSignal(
    inject(ActivatedRoute).params.pipe(map((params) => Number(params['id'])))
  );

  product = computed(() => this.getProduct(this.productId()!));

  getProduct(id: number) {
    return this.query.querySignal({
      queryKey: ['product', id],
      queryFn: () => of({ id }).pipe(delay(2 * 1000)),
    });
  }
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterModule],
  template: `
    <h1>Hello from {{ name }}!</h1>
    <a [routerLink]="['/1']">goto product 1</a>
    <hr>
    <router-outlet></router-outlet>
  `,
})
export class App {
  name = 'Angular';
}

bootstrapApplication(App, {
  providers: [provideRouter([{ path: ':id', component: ProductComponent }])],
});

内容的提问来源于stack exchange,提问作者Jon You

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:52:27