gpt4 book ai didi

javascript - 使用 forRoot 依赖于模块的 Angular 传递服务

转载 作者:行者123 更新时间:2023-12-05 00:39:26 25 4
gpt4 key购买 nike

我有一个基于 JWT 的身份验证服务。为了在我的所有项目中重用这个服务,我创建了一个应该随 npm 一起提供的库。
为了使这项服务正常工作,我需要一些 API 调用。在每个项目中,API 可能看起来完全不同,所以我不想在我的库中提供这个功能,而是注入(inject)另一个服务来处理我的 API 调用。
我的想法是创建一个包含我的服务的模块,并提供一个接口(interface)来描述 API-Calls 的服务并将其注入(inject) forRoot。问题是我的 api 服务有一些依赖项,比如 HttpClient,我不能在我的 app.module 中简单地实例化它。
我的图书馆看起来像:
auth.module.ts

import { NgModule, ModuleWithProviders, InjectionToken } from '@angular/core';
import { AuthService } from '../services/auth.service';
import { AuthAPI } from '../models/authAPI';
import { AuthapiConfigService } from '../services/authapi-config.service';


@NgModule()
export class AuthModule {

static forRoot(apiService: AuthAPI): ModuleWithProviders {
return {
ngModule: AuthModule,
providers: [
AuthService,
{
provide: AuthapiConfigService,
useValue: apiService
}
]
};
}
}
auth-api.interface.ts
import { Observable } from 'rxjs';

export interface AuthAPI {
reqLogin(): Observable<{ access_token: string; }>;
reqRegister(): Observable<{ access_token: string; }>;
}
auth-api-config.service.ts
import { InjectionToken } from '@angular/core';
import { AuthAPI } from '../models/authAPI';
/**
* This is not a real service, but it looks like it from the outside.
* It's just an InjectionTToken used to import the config object, provided from the outside
*/
export const AuthapiConfigService = new InjectionToken<AuthAPI>('API-Service');
auth.service.ts
 constructor(@Inject(AuthapiConfigService) private apiService) {}
我如何尝试实现它:
auth-rest-service.ts
import { Injectable } from '@angular/core';
import { AuthAPI } from 'projects/library-project/src/lib/auth/models/authAPI';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Injectable({
providedIn: 'root'
})
export class AuthRestService implements AuthAPI {

constructor(private http: HttpClient) {}

reqLogin(): Observable<{ access_token: string; }> {
return this.http.post<{access_token: string}>(`/login`, 'test');
}

reqRegister(): Observable<{ access_token: string; }> {
return this.http.post<{access_token: string}>(`/login`, 'test');
}

}
app.module.ts
import { AuthRestService } from './components/auth-service/auth-rest.service';


@NgModule({
declarations: [
...
],
imports: [
...
AuthModule.forRoot(AuthRestService),
...
],
providers: [AuthModule],
bootstrap: [AppComponent]
})
export class AppModule { }
由于此服务具有的依赖项(HttpClient),我无法创建 AuthRestService 的实例。有什么方法可以告诉 Angular 为我提供这项服务。

最佳答案

这可以通过使用 angular 的 Injector 来实现。 .

import { Injector, ModuleWithProviders, NgModule, Optional, Provider, SkipSelf } from '@angular/core';
import { isFunction } from 'lodash';

export function resolveService(cfg: SharedConfig, inj: Injector): IncompleteService {
const provider = cfg?.service;
// if service is an angular provider, use Injector, otherwise return service instance as simple value
const service = isFunction(service) ? inj.get(provider) : provider;
return service;
}

/**
* Service to be implemented from outside the module.
*/
@Injectable()
export abstract class IncompleteService {
abstract strategyMethod();
}

// Optional: A config object is optional of course, but usually it fits the needs.
export interface SharedConfig {
service: IncompleteService | Type<IncompleteService> | InjectionToken<IncompleteService>;
// other config properties...
}

/*
* Optional: If a Config interface is used, one might resolve the config itself
* using other dependencies (e.g. load JSON via HTTPClient). Hence an InjectionToken
* is necessary.
*/
export const SHARED_CONFIG = new InjectionToken<SharedConfig>('shared-config');

// Optional: If SharedConfig is resolved with dependencies, it must be provided itself.
export type ModuleConfigProvider = ValueProvider | ClassProvider | ExistingProvider | FactoryProvider;

/**
* One can provide the config as is, i.e. "{ service: MyService }" or resolved by
* injection, i.e.
* { provide: SHARED_CONFIG: useFactory: myConfigFactory, deps: [DependentService1, DependentService2] }
*/
@NgModule({
declarations: [],
imports: []
})
export class SharedModule {
static forRoot(config: SharedConfig | ModuleConfigProvider): ModuleWithProviders<SharedModule> {
// dynamic (config is Provider) or simple (config is SharedConfig)
return {
ngModule: SharedModule,
providers: [
(config as ModuleConfigProvider).provide ? (config as Provider) : { provide: SHARED_CONFIG, useValue: config },
{ provide: IncompleteService, useFactory: resolveService, deps: [SHARED_CONFIG, Injector] },
// ... provide additional things
],
};
}


/**
* In general not really useful, because usually an instance of IncompleteService
* need other dependencies itself. Hence you cannot provide this instance without
* creating it properly. But for the sake of completeness, it should work as well.
*/
@NgModule({
declarations: [],
imports: []
})
export class MostSimpleSharedModule {
static forRoot(service: IncompleteService): ModuleWithProviders<SharedModule> {
// dynamic (config is Provider) or simple (config is SharedConfig)
return {
ngModule: SharedModule,
providers: [
{ provide: IncompleteService, useValue: service },
// ... provide additional things
],
};
}
编辑
如果你真的需要一个接口(interface)iso。一个(可注入(inject)的)抽象类 IncompleteService , 你只需要定义另一个 InjectionToken<IncompleteServiceInterface>并明确提供此 token 。

关于javascript - 使用 forRoot 依赖于模块的 Angular 传递服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62412960/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com