使用灵活的NgModule提供程序进行角度服务抽象&条件依赖加载

时间:2018-02-01 14:14:04

标签: angular

我正在编写一个Angular库模块,希望灵活配置,同时尽可能简单地在消费应用中使用,支持急切和延迟加载,并尽可能快地加载。

这个想法是创建和公开一些Web组件(库的大部分),以及(可选)一个服务,这是一个默认实现,用于从参考API服务器获取数据以支持这些组件。目标是让用户使用带有或不带默认服务的组件,和/或注入组件应该使用的自己的服务实现。同时,它不应该加载未使用的依赖项(例如,如果应用程序想要注入不使用Http调用的自定义服务,则不需要导入Http模块。)

到目前为止,我已经发布了以下内容。我的问题是:

  1. 这是一个合理的方式来做这件事还是我过度复杂?
  2. 当使用默认的库服务实现(下面的application-default.ts)时,我需要在某处注入一个Http提供程序。有没有什么办法可以在这种情况下动态导入Http模块(即使用包含的默认服务时),而不需要消费应用程序必须知道将其包含在其导入定义中?
  3. library.ts

    abstract class ServiceImplementation {
    }
    
    @Injectable()
    export class DefaultServiceImplementation extends ServiceImplementation {
        constructor(private http: Http) {
        }
    
        doSomething() {
            return this.http.get(...);
        }
    }
    
    @Component({
        selector: 'my-component',
        template: ''
    })
    export class MyComponent {
        constructor(@Optional() private service: ServiceImplementation) {
            if(service) {
                service.doSomething().subscribe(...);
            }
        }
    }
    
    @NgModule({
        imports: [
            // AngularDependanciesRequiredOnlyForMyComponent
        ],
        declarations: [
            MyComponent
        ],
        exports: [
            MyComponent
        ]
    })
    export class LibraryModule {
        static forRoot(): ModuleWithProviders {
            return {
                ngModule: LibraryModule,
                providers: [
                    { provide: ServiceImplementation, useClass: DefaultServiceImplementation }
                ]
            };
        }
    }
    

    application-provide.ts - 使用库但提供自定义服务。

    @Injectable()
    export class MyServiceImplementation extends ServiceImplementation {
        doSomething() {
            return Observable.of(...);
        }
    }
    
    @NgModule({
        imports: [
            BrowserModule,
            LibraryModule
        ],
        declarations: [
            AppComponent
        ],
        providers: [
            { provide: ServiceImplementation, useClass: MyServiceImplementation }
        ]
    })
    export class AppModule {
    }
    

    application-default.ts - 使用库提供的服务

    @NgModule({
        imports: [
            BrowserModule,
            LibraryModule.forRoot()
        ],
        declarations: [
            AppComponent
        ]
    })
    export class AppModule {
    }   
    

1 个答案:

答案 0 :(得分:-1)

这样的东西我也在我们的产品上实现。创建“服务”抽象是有意义的。 我不知道是否可以添加动态模块,如Http或FormModule。恕我直言,它不需要考虑导入HttpModule,因为在AOT上 - 构建angular-cli会丢弃未使用的元素。

我有一个实现来将flat es模块加载和导入到我们的应用程序中,但这是另一回事。