我正在致电给您寻求使用哪种方法的帮助:我已经测试了很多方法来解决我的问题,并且我至少有4种有效的解决方案,但是我不知道哪种方法是最好的,以及是否其中一些仅由于我做过的其他事情的副作用而起作用,不应该使用...
我在文档中找不到任何内容可以指向这些解决方案中的一种(或另一种)
首先,这是我的情况:我正在构建一个应用程序,该应用程序连接到数据的API并构建不同的部分,每个部分都包含dataviz。
我将站点的各个部分构建为模块,但是它们共享一个名为DataService的服务(这些模块中的每个模块都将使用DataService来获取和处理数据)。
我的DataService需要一个配置文件,该文件包含许多特定于每个部分的选项,并存储在其自己的文件夹中。
因此,我需要在module.ts文件的providers部分的每个部分分别提供DataService,并且似乎很好的做法是避免将DataService复制到每个模块...
因此,文件的架构为:
--Dashboard module
----data.service.ts
----Section1 module
------Section1 config file
----Section2 module
------Section2 config file
我尝试了在模块模块文件中似乎都起作用的多种方法:
解决方案1:注入(inject)
(即使没有在任何地方都看不到引号,我也无法使注入(inject)工作正常进行)
模块文件:
import { DataService } from '../services/data.service';
import viewConfig from './view.config.json';
@NgModule({
imports: [ ... ],
declarations: [ ... ],
providers: [
{ provide: 'VIEW_CONFIG', useValue: viewConfig },
DataService,
]})
export class Section1Module { }
节文件:
@Injectable()
export class DataService {
constructor(@Inject('VIEW_CONFIG') private viewConfig : any) {}
}
解决方案2:工厂提供者
在ng服务重启后无法正常工作(请参阅更新)
灵感来自https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#factory-provider
模块文件:
import { DataService } from '../services/data.service';
import viewConfig from './view.config.json';
export let VIEW_CONFIG = new InjectionToken<any>('');
let dataServiceFactory = (configObject):DataService => {
return new DataService(configObject)
}
@NgModule({
imports: [ ... ],
declarations: [ ... ],
providers: [
{ provide: VIEW_CONFIG, useValue: viewConfig },
{
provide : DataService,
useFactory : dataServiceFactory,
deps : [VIEW_CONFIG]
},
]})
export class Section1Module { }
节文件:
@Injectable()
export class DataService {
constructor(private viewConfig : any) {}
}
解决方案3:具有直接实例化的自定义提供程序
在ng服务重启后无法正常工作(请参阅更新)
模块文件:
import { DataService } from '../services/data.service';
import viewConfig from './view.config.json';
@NgModule({
imports: [ ... ],
declarations: [ ... ],
providers: [
{ provide: DataService, useValue : new DataService(viewConfig) },
]})
export class Section1Module { }
节文件:
@Injectable()
export class DataService {
constructor(private viewConfig : any) {}
}
解决方案4:带有工厂的自定义提供程序
在ng服务重启后无法正常工作(请参阅更新)
与解决方案3非常相似...
模块文件:
import { DataService } from '../services/data.service';
import viewConfig from './view.config.json';
let dataServiceFactory = (configObject) => { return new DataService(configObject) }
@NgModule({
imports: [ ... ],
declarations: [ ... ],
providers: [
{ provide: DataService, useValue : dataServiceFactory(viewConfig) }
]})
export class Section1Module { }
节文件:
@Injectable()
export class DataService {
constructor(private viewConfig : any) {}
}
解决方案5
使用从服务文件AND和注入(inject) token 导出的工厂
模块文件:
export const VIEW_CONFIG = new InjectionToken<any>('');
@NgModule({
imports: [ ... ],
declarations: [ ... ],
providers: [
{ provide: VIEW_CONFIG, useValue: viewConfig },
{ provide : DataService,
useFactory: dataServiceFactory,
deps : [VIEW_CONFIG] }
]})
export class Section1Module { }
节文件:
@Injectable()
export class DataService {
constructor(private viewConfig : any) {}
}
export function dataServiceFactory(configObject) {
return new DataService(configObject);
}
对于“什么是正确的解决方案?”的任何批评,想法和新的领导,我都持开放态度。甚至“这是正确的解决方案吗?”
非常感谢 ! :D
更新
有一次,我意识到我的Angular-CLI表现异常,并且如果我杀死本地服务器并执行“ng服务”,其中某些方法将无法正常工作。
更奇怪的是,它在杀死CLI本地服务器并重新启动后无法正常工作,但是下次我保存文件并重新编译CLI时,它可以正常工作...
解决方案1 :仍在工作
解决方案2/解决方案3 :失败,并出现错误:
Error encountered resolving symbol values statically. Calling function
'DataService', function calls are not supported. Consider replacing the
function or lambda with a reference to an exported function
解决方案4 :失败,并显示以下错误:
Error encountered resolving symbol values statically. Reference to a non-exported function
添加了解决方案5
最佳答案
我使用 View 的配置数据的方法是这样的:
我的配置文件:
export const IBO_DETAILS_GENERAL = {
iboCode: 'IBOsFormCodeField',
iboGivenName: 'IBOsFormGivenNameField',
iboFamilyName: 'IBOsFormFamilyNameField',
iboEmail: 'IBOsFormEmailField',
};
export const IBO_DETAILS_ACCOUNT = [];
我的 View 组件:
import { IBO_DETAILS_GENERAL } from './ibo-details-formfields';
@Component({
selector: 'ibo-details-general',
templateUrl: './ibo-details-general.component.html',
styles: [],
})
export class IboDetailsGeneral extends FilterDataMappingManipulator implements OnInit, OnDestroy {
// Initial constants,vectors and component mapping
private formFields = IBO_DETAILS_GENERAL;
所以,这样,我在
config
中有我的formFields
。而且我可以在该组件范围内的任何地方使用它。我目前正在使用它来生成动态表单字段(输入,选择等),具体取决于我从API调用中获取的数据。
但是您可以使用该对象(在我的情况下为
formFields
)查找所需内容,并将其作为参数发送到您的服务。同样,在将共享服务置于更高级别上也做得很好。我相信是最好的方法。但是我不会将其添加到每个组件的
providers
中,而是将其添加到组件的模块中。像这样:@NgModule({
declarations: [
ChildComp1,
ChildComp2
],
imports: [
],
providers: [
SharedService
]
})
export class SectionModule {
}
这样,
ChildComp1
和ChildComp2
将可以访问SharedService
,而不必将其添加到组件的代码中。例如,当您定义用户部分时,这可以很好地工作。可以说,在内部,您在
UsersModule
中声明了providers
,然后在UsersSharedService
中声明了declarations
和UsersLeftPanel
(示例)。更新1:
在服务中使用config的示例。
想象一下,共享服务具有以下方法:
getData() {
// do Stuff
let myData = {}; // Result of the stuff we did
this.dataSubject.next(myData);
}
在您的组件中,您可以这样称呼:
this.myService.getData();
正确的?
现在,还记得我们已经声明了我们的配置吗?将其添加到调用中。
this.myService.getData(this.formFields);
并且,在我们的服务中:
getData(currentConfig) {
// do Stuff depending on currentConfig obj received as parameter
let myData = {}; // Result of the stuff we did
this.dataSubject.next(myData);
}
这样,您通过不同的配置调用我们共享服务的
UsersRightPanel
方法。这样,您不必将服务包含在许多getData()
中,也不必复制/粘贴处理配置的逻辑,您可以将其包含在共享服务中,因此,所有子代都可以访问它。更新2:
按照您的解决方案5方法,我认为您缺少
providers
。试试这个:
export function dataServiceFactory(configObject) {
return () => new DataService(configObject);
}
providers: [
{ provide: VIEW_CONFIG, useValue: viewConfig },
{ provide : DataService,
useFactory: dataServiceFactory,
deps : [VIEW_CONFIG],
multi: true }
]})
导出函数中的
multi: true
是键:return
。这就是我在项目中的方式:
export function initConfigFactory(userConfig: UserConfig) {
return () => userConfig.getUsersConfig();
}
其中
return () =>
是获取用户配置的服务调用。providers: [
{
provide: APP_INITIALIZER,
useFactory: initConfigFactory,
deps: [UserConfig],
multi: true
}
]
这非常接近您的解决方案5,请尝试一下!