Angular如何从Service向下传递变量至嵌套Service?
实现方案
根据你的需求,这里提供两种可行的实现方式,都能保证ProductService不直接依赖APIService,而是通过FacadeService作为唯一入口传递参数。
方案一:利用Angular依赖注入令牌(推荐)
这种方式符合Angular的依赖注入最佳实践,通过注入令牌传递动态的controllerName,同时为每个业务服务(如ProductService)创建专属的FacadeService和APIService实例。
步骤1:定义注入令牌
创建一个单独的令牌文件,用来标记需要传递的controllerName:
// tokens.ts import { InjectionToken } from '@angular/core'; export const CONTROLLER_NAME = new InjectionToken<string>('Controller Name');
步骤2:修改APIService
移除providedIn: 'root',通过注入令牌获取controllerName:
// APIService.ts import { Inject, Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { CONTROLLER_NAME } from './tokens'; @Injectable() export class APIService<T> { private baseUrl = 'https://localhost:1337/api/'; public url: string; constructor( private http: HttpClient, @Inject(CONTROLLER_NAME) private controllerName: string ) { this.url = this.baseUrl + controllerName; } // 可在此添加HTTP请求方法,比如getAll()等 }
步骤3:修改FacadeService
同样移除providedIn: 'root',直接注入APIService即可,无需处理controllerName:
// FacadeService.ts import { Injectable } from '@angular/core'; import { APIService } from './api.service'; @Injectable() export class FacadeService<T> { constructor(public api: APIService<T>) {} // 可在此封装APIService的方法,对外提供统一入口 }
步骤4:配置ProductService的专属依赖
在ProductService中提供专属的令牌值、FacadeService和APIService,确保实例唯一:
// ProductService.ts import { Injectable } from '@angular/core'; import { FacadeService } from './facade.service'; import { APIService } from './api.service'; import { CONTROLLER_NAME } from './tokens'; @Injectable({ providedIn: 'root', providers: [ { provide: CONTROLLER_NAME, useValue: 'product' }, APIService, FacadeService ] }) export class ProductService { constructor(private facadeService: FacadeService<Product>) { // 测试:此时facadeService.api.url应为"https://localhost:1337/api/product" console.log(this.facadeService.api.url); } // 业务方法,通过FacadeService调用API getProducts() { return this.facadeService.api.http.get(this.facadeService.api.url); } }
如果有多个类似的业务服务(如UserService),只需复制上述配置,将CONTROLLER_NAME的useValue改为对应的名称即可。
方案二:手动初始化APIService实例
这种方式更简单直接,通过FacadeService的初始化方法传递controllerName,手动创建APIService实例。
步骤1:修改APIService
保留构造函数接收controllerName,无需依赖注入令牌:
// APIService.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable() export class APIService<T> { private baseUrl = 'https://localhost:1337/api/'; public url: string; constructor( private http: HttpClient, private controllerName: string ) { this.url = this.baseUrl + controllerName; } }
步骤2:修改FacadeService
添加initialize方法,接收controllerName并创建APIService实例:
// FacadeService.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { APIService } from './api.service'; @Injectable({ providedIn: 'root' }) export class FacadeService<T> { public api?: APIService<T>; constructor(private http: HttpClient) {} initialize(controllerName: string) { this.api = new APIService<T>(this.http, controllerName); } }
步骤3:修改ProductService
在构造函数中调用FacadeService的initialize方法,传入controllerName:
// ProductService.ts import { Injectable } from '@angular/core'; import { FacadeService } from './facade.service'; @Injectable({ providedIn: 'root' }) export class ProductService { private controllerName = 'product'; constructor(private facadeService: FacadeService<Product>) { this.facadeService.initialize(this.controllerName); // 测试:此时facadeService.api.url应为"https://localhost:1337/api/product" console.log(this.facadeService.api?.url); } }
内容的提问来源于stack exchange,提问作者Starfish
相关产品推荐
相关产品推荐

