Angular 13如何根据local/QA环境动态注入本地服务与API服务
Angular 13 动态注入服务实现方案
步骤1:定义公共服务接口
首先为两个API服务定义统一的调用接口,保证两者对外暴露的方法签名一致:api.interface.ts
import { Observable } from 'rxjs'; import { LoginRequest } from '../login/login-request'; export interface IApiService { userLogin(loginRequest?: LoginRequest): Observable<any>; getUserList(): Observable<any>; }
步骤2:调整两个API服务实现接口
分别修改api-local.service.ts和api.service.ts,实现上述接口,对齐方法名和参数:
修改后 api-local.service.ts
import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { LoginRequest } from '../login/login-request'; import { IApiService } from './api.interface'; @Injectable({ providedIn: 'root' }) export class ApiLocalService implements IApiService { constructor(private httpClient: HttpClient) { } private headers = new HttpHeaders({ 'Content-Type': 'application/json; charset=utf-8', 'Accept': 'application/json, text/plain' }); userLogin(): Observable<any>{ console.log("inside LOCAL API service"); return this.httpClient.get('../assets/data/login.json', {headers:this.headers}); } getUserList(): Observable<any>{ return this.httpClient.get('../assets/data/userList.json' , { headers: this.headers }) } }
修改后 api.service.ts
import { Inject, Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { LoginRequest } from '../login/login-request'; import { EnvironmentConfig, ENV_CONFIG } from './environment-config.interface'; import { IApiService } from './api.interface'; @Injectable({ providedIn: 'root' }) export class ApiService implements IApiService { public apiUrl: string; constructor(@Inject(ENV_CONFIG) config: EnvironmentConfig,private httpClient: HttpClient,) { this.apiUrl = `${config.environment.baseUrl}`; } private headers = new HttpHeaders({ 'Content-Type': 'application/json; charset=utf-8', 'Accept': 'application/json, text/plain' }); userLogin(loginRequest: LoginRequest): Observable<any>{ console.log("inside QA API service"); return this.httpClient.post(`${this.apiUrl}/auth-service/login`, loginRequest, {headers:this.headers}); } getUserList(): Observable<any>{ return this.httpClient.get(`${this.apiUrl}/user/list` , { headers: this.headers }) } }
步骤3:修改AuthService实现动态注入
修改auth-service.ts,使用Angular的Injector动态获取服务实例,无需硬编码注入固定服务:
修改后核心代码
import { EventEmitter, Injectable, Output, Injector } from '@angular/core'; import { Observable, throwError } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { LoginRequest } from '../login/login-request'; import { LoginResponse } from '../login/login-response'; import { LocalStorageService } from 'ngx-webstorage'; import { map, tap ,catchError} from 'rxjs/operators'; import { environment } from 'src/environments/environment'; import { IApiService } from './api.interface'; import { ApiLocalService } from './api-local.service'; import { ApiService } from './api.service'; @Injectable({ providedIn: 'root' }) export class AuthService { private API_URL = environment.API_URL; private roles: Array<string> = []; private apiService: IApiService; // 公共接口类型的服务实例 @Output() loggedIn: EventEmitter<boolean> = new EventEmitter(); @Output() username: EventEmitter<string> = new EventEmitter(); @Output() admin: EventEmitter<boolean> = new EventEmitter(); @Output() superAdmin: EventEmitter<boolean> = new EventEmitter(); @Output() client: EventEmitter<boolean> = new EventEmitter(); refreshTokenPayload = { refreshToken: this.getRefreshToken(), username: this.getUserName() } constructor( private httpClient: HttpClient, private localStorage: LocalStorageService, private injector: Injector // 注入Angular注入器 ) { // 初始化时根据环境判断要使用的服务实例 this.apiService = environment.env === 'local' ? this.injector.get(ApiLocalService) : this.injector.get(ApiService); } adminLogin(loginRequest: LoginRequest): Observable<boolean> { console.log("loginrequest:"+loginRequest); // 调用动态获取的服务的统一登录方法 return this.apiService.userLogin(environment.env === 'qa' ? loginRequest : undefined) .pipe(map(data => { console.log(data) if(data.roles.find((role: string) => role !='ROLE_SUPER_ADMIN' && role !='ROLE_ADMIN' && role !='ROLE_CLIENT')){ return false; }else{ this.localStorage.store('authenticationToken', data.authenticationToken); this.localStorage.store('username', data.username); this.localStorage.store('refreshToken', data.refreshToken); this.localStorage.store('expiresAt', data.expiresAt); this.localStorage.store('roles', JSON.stringify(data.roles)); this.loggedIn.emit(true); this.username.emit(data.username); if(data.roles.find((role: string) => role =='ROLE_ADMIN')){ this.admin.emit(true); } if(data.roles.find((role: string) => role =='ROLE_SUPER_ADMIN')){ this.superAdmin.emit(true); } if(data.roles.find((role: string) => role =='ROLE_CLIENT')){ this.client.emit(true); } return true; } })); } // 其他原有方法保持不变 }
配置校验
确保你的环境配置文件environment.ts中已添加环境标识字段:
- 本地环境配置:
env: 'local' - QA环境配置:
env: 'qa'
后续如需新增其他环境,仅需要修改构造函数中的服务判断逻辑即可,无需改动业务调用代码,可扩展性更高。
内容的提问来源于stack exchange,提问作者Shruthy
相关产品推荐
相关产品推荐

