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

Angular18独立配置中如何注册自定义DataService重写GetAll方法?

问题描述

我基于NGRX/Entity创建了继承自DefaultDataService的自定义DataService,用来请求自定义URL获取JSON数据。但因为用的是Angular独立配置(无NgModule),没法注册这个自定义服务,导致重写的getAll方法从来没生效过。

相关依赖版本:

{
  "@angular/animations": "^18.2.0",
  "@angular/cdk": "^18.2.0",
  "@angular/common": "^18.2.0",
  "@angular/compiler": "^18.2.0",
  "@angular/core": "^18.2.0",
  "@angular/forms": "^18.2.0",
  "@angular/material": "^18.2.0",
  "@angular/platform-browser": "^18.2.0",
  "@angular/platform-browser-dynamic": "^18.2.0",
  "@angular/platform-server": "^18.2.0",
  "@angular/router": "^18.2.0",
  "@angular/ssr": "^18.2.0",
  "@coreui/angular": "^5.2.14",
  "@ngrx/data": "^18.0.2",
  "@ngrx/effects": "^18.0.2",
  "@ngrx/entity": "^18.0.2",
  "@ngrx/router-store": "^18.0.2",
  "@ngrx/store": "^18.0.2",
  "@ngrx/store-devtools": "^18.0.2",
  "express": "^4.18.2",
  "rxjs": "~7.8.0",
  "tslib": "^2.3.0",
  "zone.js": "~0.14.10"
}

entity-metadata.ts 文件内容

import {
  EntityMetadataMap,
  EntityDataModuleConfig,
} from '@ngrx/data';
const entityMetadata: EntityMetadataMap = {
  Country: {}
};

const pluralNames = { Country: 'Countries' };

export const entityConfig: EntityDataModuleConfig = {
  entityMetadata,
  pluralNames
};

app.config.ts 文件内容

import {ApplicationConfig, provideZoneChangeDetection, isDevMode} from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import {provideStore} from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';


import * as fromApp from './store/app.reducer';
import {provideClientHydration} from '@angular/platform-browser';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideHttpClient } from '@angular/common/http';
import { provideStoreDevtools } from '@ngrx/store-devtools';

import {AuthEffects} from "./pages/auth/store/auth.effects";
import { provideRouterStore } from '@ngrx/router-store';
import {provideEntityData, withEffects} from '@ngrx/data';
import {entityConfig} from './entity-metadata';


export const appConfig: ApplicationConfig = {
  providers: [provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideClientHydration(),
    provideAnimationsAsync(),
    provideStore(fromApp.appReducer, { runtimeChecks: {
            strictActionImmutability: true
        } }),
    provideHttpClient(),
    provideEffects(AuthEffects),
    provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
    provideRouterStore(),
    provideEntityData(entityConfig, withEffects())
  ]
};

自定义DataService 文件内容

虽然已经设置了providedIn: 'root',但服务仍未被调用:

import { Injectable } from '@angular/core';
import {DefaultDataService, HttpUrlGenerator} from "@ngrx/data";
import {Countries, Country} from "../../../models/countries.model";
import {HttpClient} from "@angular/common/http";
import {map, Observable} from "rxjs";
import {baseUrl} from "../../../../../environments/environments";

@Injectable({
  providedIn: 'root'
})
export class CountryDataService extends DefaultDataService<Country>{

  constructor(http:HttpClient, httpUrlGenerator:HttpUrlGenerator) {
    super('Country', http, httpUrlGenerator);
  }

  override getAll(): Observable<Country[]> {
    return this.http.get<Countries>(baseUrl + '/api/country/GetCountries')
      .pipe(
        map(res => res["COUNTRIES"])
      )
  }
}

Resolver 文件内容

import { Injectable } from '@angular/core';
import {
  ActivatedRouteSnapshot,
  Resolve,
  RouterStateSnapshot,
} from '@angular/router';
import { map, Observable } from 'rxjs';
import { CountryEntityService } from './country-entity.service';
import {CountryDataService} from "./country-data.service";
import {CountryActions} from './action-types';

@Injectable({ providedIn: 'root' })
export class CountryResolver implements Resolve<boolean> {
  constructor(
    private countryService: CountryEntityService
  ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot,
  ): Observable<boolean> {
    return this.countryService.getAll().pipe(map((countries) => !!countries));
  }
}

解决方案

在Angular独立配置中,NGRX Data不会自动发现自定义的DefaultDataService实现,即使你加了providedIn: 'root'。需要手动把自定义服务注册到NGRX Data的配置里,具体操作如下:

  • 修改entity-metadata.ts,为Country实体指定dataService
    在entityMetadata的Country配置中添加dataService属性,指向自定义的CountryDataService:

    import {
      EntityMetadataMap,
      EntityDataModuleConfig,
    } from '@ngrx/data';
    // 引入自定义服务
    import { CountryDataService } from './path-to-your-service/country-data.service';
    
    const entityMetadata: EntityMetadataMap = {
      Country: {
        dataService: CountryDataService // 指定自定义数据服务
      }
    };
    
    const pluralNames = { Country: 'Countries' };
    
    export const entityConfig: EntityDataModuleConfig = {
      entityMetadata,
      pluralNames
    };
    
  • 在app.config.ts中注册DataService
    需要用provideDataService函数把自定义服务添加到providers数组中,这个函数来自@ngrx/data:

    import {ApplicationConfig, provideZoneChangeDetection, isDevMode} from '@angular/core';
    import { provideRouter } from '@angular/router';
    import { routes } from './app.routes';
    import {provideStore} from '@ngrx/store';
    import { provideEffects } from '@ngrx/effects';
    
    import * as fromApp from './store/app.reducer';
    import {provideClientHydration} from '@angular/platform-browser';
    import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
    import { provideHttpClient } from '@angular/common/http';
    import { provideStoreDevtools } from '@ngrx/store-devtools';
    
    import {AuthEffects} from "./pages/auth/store/auth.effects";
    import { provideRouterStore } from '@ngrx/router-store';
    import {provideEntityData, withEffects, provideDataService} from '@ngrx/data'; // 引入provideDataService
    import {entityConfig} from './entity-metadata';
    import { CountryDataService } from './path-to-your-service/country-data.service'; // 引入自定义服务
    
    
    export const appConfig: ApplicationConfig = {
      providers: [provideZoneChangeDetection({ eventCoalescing: true }),
        provideRouter(routes),
        provideClientHydration(),
        provideAnimationsAsync(),
        provideStore(fromApp.appReducer, { runtimeChecks: {
                strictActionImmutability: true
            } }),
        provideHttpClient(),
        provideEffects(AuthEffects),
        provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
        provideRouterStore(),
        provideEntityData(entityConfig, withEffects()),
        provideDataService(CountryDataService) // 注册自定义数据服务
      ]
    };
    
  • 验证是否生效
    运行项目后,当CountryEntityService.getAll()被调用时,应该会触发你自定义的getAll方法,请求指定的URL。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:04:51