From 4544c1a5bcabb1fa3e60b6fe6c2f6e1a5215ab5c Mon Sep 17 00:00:00 2001 From: Ed Morales Date: Wed, 24 May 2017 11:28:22 -0700 Subject: [PATCH] perf(providers): make sure all services are singleton (#610) * perf(providers): make sure all services are singleton when using modules, make sure we reuse the instance provided by the parent module rather than creation a new instance. all covalent services are meant to be singleton and app wise instances. * fix(http): revert to not singleton http service since devs might want a diff http per module * chore(http): remove unused imports --- src/platform/core/data-table/data-table.module.ts | 5 +++-- .../core/data-table/services/data-table.service.ts | 14 +++++++++++++- src/platform/core/dialogs/dialogs.module.ts | 4 ++-- .../core/dialogs/services/dialog.service.ts | 14 +++++++++++++- src/platform/core/loading/loading.module.ts | 8 ++++---- .../core/loading/services/loading.factory.ts | 14 +++++++++++++- .../core/loading/services/loading.service.ts | 14 +++++++++++++- src/platform/core/media/media.module.ts | 4 ++-- src/platform/core/media/services/media.service.ts | 14 +++++++++++++- src/platform/dynamic-forms/dynamic-forms.module.ts | 4 ++-- .../services/dynamic-forms.service.ts | 14 +++++++++++++- src/platform/http/http.module.ts | 13 ++++++++----- 12 files changed, 99 insertions(+), 23 deletions(-) diff --git a/src/platform/core/data-table/data-table.module.ts b/src/platform/core/data-table/data-table.module.ts index 6897c24a14..2e5f678029 100644 --- a/src/platform/core/data-table/data-table.module.ts +++ b/src/platform/core/data-table/data-table.module.ts @@ -8,9 +8,10 @@ import { TdDataTableColumnComponent } from './data-table-column/data-table-colum import { TdDataTableCellComponent } from './data-table-cell/data-table-cell.component'; import { TdDataTableRowComponent } from './data-table-row/data-table-row.component'; import { TdDataTableTableComponent } from './data-table-table/data-table-table.component'; -import { TdDataTableService } from './services/data-table.service'; import { TdDataTableTemplateDirective } from './directives/data-table-template.directive'; +import { TdDataTableService, DATA_TABLE_PROVIDER } from './services/data-table.service'; + const TD_DATA_TABLE: Type[] = [ TdDataTableComponent, TdDataTableTemplateDirective, @@ -45,7 +46,7 @@ export { TdDataTableTableComponent } from './data-table-table/data-table-table.c TD_DATA_TABLE, ], providers: [ - TdDataTableService, + DATA_TABLE_PROVIDER, ], }) export class CovalentDataTableModule { diff --git a/src/platform/core/data-table/services/data-table.service.ts b/src/platform/core/data-table/services/data-table.service.ts index 906b2155c3..d965d96bd4 100644 --- a/src/platform/core/data-table/services/data-table.service.ts +++ b/src/platform/core/data-table/services/data-table.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; import { TdDataTableSortingOrder, ITdDataTableColumn } from '../data-table.component'; @@ -75,3 +75,15 @@ export class TdDataTableService { return data; } } + +export function DATA_TABLE_PROVIDER_FACTORY( + parent: TdDataTableService): TdDataTableService { + return parent || new TdDataTableService(); +} + +export const DATA_TABLE_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdDataTableService, + deps: [[new Optional(), new SkipSelf(), TdDataTableService]], + useFactory: DATA_TABLE_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/dialogs/dialogs.module.ts b/src/platform/core/dialogs/dialogs.module.ts index c42b48d416..ab5a43f29b 100644 --- a/src/platform/core/dialogs/dialogs.module.ts +++ b/src/platform/core/dialogs/dialogs.module.ts @@ -10,7 +10,7 @@ import { TdDialogComponent, TdDialogTitleDirective, import { TdAlertDialogComponent } from './alert-dialog/alert-dialog.component'; import { TdConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component'; import { TdPromptDialogComponent } from './prompt-dialog/prompt-dialog.component'; -import { TdDialogService } from './services/dialog.service'; +import { TdDialogService, DIALOG_PROVIDER } from './services/dialog.service'; const TD_DIALOGS: Type[] = [ TdAlertDialogComponent, @@ -47,7 +47,7 @@ export { TdDialogService, TdDialogComponent, TdDialogTitleDirective, TD_DIALOGS, ], providers: [ - TdDialogService, + DIALOG_PROVIDER, ], entryComponents: [ TD_DIALOGS_ENTRY_COMPONENTS, diff --git a/src/platform/core/dialogs/services/dialog.service.ts b/src/platform/core/dialogs/services/dialog.service.ts index a6a36851cf..ccb22fdb63 100644 --- a/src/platform/core/dialogs/services/dialog.service.ts +++ b/src/platform/core/dialogs/services/dialog.service.ts @@ -1,4 +1,4 @@ -import { Injectable, ViewContainerRef } from '@angular/core'; +import { Injectable, ViewContainerRef, Provider, SkipSelf, Optional } from '@angular/core'; import { MdDialog, MdDialogRef, MdDialogConfig, ComponentType } from '@angular/material'; import { TdAlertDialogComponent } from '../alert-dialog/alert-dialog.component'; @@ -142,3 +142,15 @@ export class TdDialogService { } } + +export function DIALOG_PROVIDER_FACTORY( + parent: TdDialogService, dialog: MdDialog): TdDialogService { + return parent || new TdDialogService(dialog); +} + +export const DIALOG_PROVIDER: Provider = { + // If there is already service available, use that. Otherwise, provide a new one. + provide: TdDialogService, + deps: [[new Optional(), new SkipSelf(), TdDialogService], MdDialog], + useFactory: DIALOG_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/loading/loading.module.ts b/src/platform/core/loading/loading.module.ts index 9224233f33..5149631a4b 100644 --- a/src/platform/core/loading/loading.module.ts +++ b/src/platform/core/loading/loading.module.ts @@ -4,8 +4,8 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MdProgressBarModule, MdProgressSpinnerModule, OverlayModule, PortalModule } from '@angular/material'; -import { TdLoadingService } from './services/loading.service'; -import { TdLoadingFactory } from './services/loading.factory'; +import { TdLoadingService, LOADING_PROVIDER } from './services/loading.service'; +import { TdLoadingFactory, LOADING_FACTORY_PROVIDER } from './services/loading.factory'; import { TdLoadingDirective } from './directives/loading.directive'; import { TdLoadingComponent } from './loading.component'; @@ -36,8 +36,8 @@ export { TdLoadingService, ITdLoadingConfig } from './services/loading.service'; TD_LOADING, ], providers: [ - TdLoadingFactory, - TdLoadingService, + LOADING_FACTORY_PROVIDER, + LOADING_PROVIDER, ], entryComponents: [ TD_LOADING_ENTRY_COMPONENTS, diff --git a/src/platform/core/loading/services/loading.factory.ts b/src/platform/core/loading/services/loading.factory.ts index e867ebfde1..ebe86e17aa 100644 --- a/src/platform/core/loading/services/loading.factory.ts +++ b/src/platform/core/loading/services/loading.factory.ts @@ -1,4 +1,4 @@ -import { Injectable, ComponentFactoryResolver, ChangeDetectorRef } from '@angular/core'; +import { Injectable, ComponentFactoryResolver, ChangeDetectorRef, Provider, SkipSelf, Optional } from '@angular/core'; import { Injector, ComponentRef, ViewContainerRef, TemplateRef } from '@angular/core'; import { TemplatePortal, Overlay, OverlayState, OverlayRef, OverlayOrigin, ComponentPortal } from '@angular/material'; import { Subject } from 'rxjs/Subject'; @@ -191,3 +191,15 @@ export class TdLoadingFactory { } } } + +export function LOADING_FACTORY_PROVIDER_FACTORY( + parent: TdLoadingFactory, componentFactoryResolver: ComponentFactoryResolver, overlay: Overlay, injector: Injector): TdLoadingFactory { + return parent || new TdLoadingFactory(componentFactoryResolver, overlay, injector); +} + +export const LOADING_FACTORY_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdLoadingFactory, + deps: [[new Optional(), new SkipSelf(), TdLoadingFactory], ComponentFactoryResolver, Overlay, Injector], + useFactory: LOADING_FACTORY_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/loading/services/loading.service.ts b/src/platform/core/loading/services/loading.service.ts index ac71493683..7be6495abf 100644 --- a/src/platform/core/loading/services/loading.service.ts +++ b/src/platform/core/loading/services/loading.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; import { ViewContainerRef, TemplateRef } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import { Observable } from 'rxjs/Observable'; @@ -230,3 +230,15 @@ export class TdLoadingService { delete this._timeouts[name]; } } + +export function LOADING_PROVIDER_FACTORY( + parent: TdLoadingService, loadingFactory: TdLoadingFactory): TdLoadingService { + return parent || new TdLoadingService(loadingFactory); +} + +export const LOADING_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdLoadingService, + deps: [[new Optional(), new SkipSelf(), TdLoadingService], TdLoadingFactory], + useFactory: LOADING_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/media/media.module.ts b/src/platform/core/media/media.module.ts index 5147ee25bd..7db5f3302c 100644 --- a/src/platform/core/media/media.module.ts +++ b/src/platform/core/media/media.module.ts @@ -3,7 +3,7 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { TdMediaService } from './services/media.service'; +import { TdMediaService, MEDIA_PROVIDER } from './services/media.service'; import { TdMediaToggleDirective } from './directives/media-toggle.directive'; const TD_MEDIA: Type[] = [ @@ -23,7 +23,7 @@ export { TdMediaService, TdMediaToggleDirective }; TD_MEDIA, ], providers: [ - TdMediaService, + MEDIA_PROVIDER, ], }) export class CovalentMediaModule { diff --git a/src/platform/core/media/services/media.service.ts b/src/platform/core/media/services/media.service.ts index 5e574464f1..757ef2ce25 100644 --- a/src/platform/core/media/services/media.service.ts +++ b/src/platform/core/media/services/media.service.ts @@ -1,4 +1,4 @@ -import { Injectable, NgZone } from '@angular/core'; +import { Injectable, NgZone, SkipSelf, Optional, Provider } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import { Observable } from 'rxjs/Observable'; @@ -90,3 +90,15 @@ export class TdMediaService { this._querySources[query].next(window.matchMedia(query).matches); } } + +export function MEDIA_PROVIDER_FACTORY( + parent: TdMediaService, ngZone: NgZone): TdMediaService { + return parent || new TdMediaService(ngZone); +} + +export const MEDIA_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdMediaService, + deps: [[new Optional(), new SkipSelf(), TdMediaService], NgZone], + useFactory: MEDIA_PROVIDER_FACTORY, +}; diff --git a/src/platform/dynamic-forms/dynamic-forms.module.ts b/src/platform/dynamic-forms/dynamic-forms.module.ts index cf0187b8f4..a87a29be4d 100644 --- a/src/platform/dynamic-forms/dynamic-forms.module.ts +++ b/src/platform/dynamic-forms/dynamic-forms.module.ts @@ -8,7 +8,7 @@ import { CovalentCommonModule } from '../core'; import { TdDynamicFormsComponent } from './dynamic-forms.component'; import { TdDynamicElementComponent, TdDynamicElementDirective } from './dynamic-element.component'; -import { TdDynamicFormsService } from './services/dynamic-forms.service'; +import { TdDynamicFormsService, DYNAMIC_FORMS_PROVIDER } from './services/dynamic-forms.service'; import { TdDynamicInputComponent } from './dynamic-elements/dynamic-input/dynamic-input.component'; import { TdDynamicTextareaComponent } from './dynamic-elements/dynamic-textarea/dynamic-textarea.component'; @@ -56,7 +56,7 @@ const TD_DYNAMIC_FORMS_ENTRY_COMPONENTS: Type[] = [ TD_DYNAMIC_FORMS_ENTRY_COMPONENTS, ], providers: [ - TdDynamicFormsService, + DYNAMIC_FORMS_PROVIDER, ], entryComponents: [ TD_DYNAMIC_FORMS_ENTRY_COMPONENTS ], }) diff --git a/src/platform/dynamic-forms/services/dynamic-forms.service.ts b/src/platform/dynamic-forms/services/dynamic-forms.service.ts index fe8310d88e..bddd3ef177 100644 --- a/src/platform/dynamic-forms/services/dynamic-forms.service.ts +++ b/src/platform/dynamic-forms/services/dynamic-forms.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; import { Validators, ValidatorFn, FormControl } from '@angular/forms'; import { CovalentValidators } from '../../core'; @@ -131,3 +131,15 @@ export class TdDynamicFormsService { return validator; } } + +export function DYNAMIC_FORMS_PROVIDER_FACTORY( + parent: TdDynamicFormsService): TdDynamicFormsService { + return parent || new TdDynamicFormsService(); +} + +export const DYNAMIC_FORMS_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdDynamicFormsService, + deps: [[new Optional(), new SkipSelf(), TdDynamicFormsService]], + useFactory: DYNAMIC_FORMS_PROVIDER_FACTORY, +}; diff --git a/src/platform/http/http.module.ts b/src/platform/http/http.module.ts index fd553058a5..3b14c07004 100644 --- a/src/platform/http/http.module.ts +++ b/src/platform/http/http.module.ts @@ -1,4 +1,4 @@ -import { NgModule, ModuleWithProviders, Injector, InjectionToken } from '@angular/core'; +import { NgModule, ModuleWithProviders, Injector, InjectionToken, Provider } from '@angular/core'; import { HttpModule, Http } from '@angular/http'; import { HttpInterceptorService, IHttpInterceptorConfig } from './interceptors/http-interceptor.service'; @@ -12,6 +12,12 @@ export function httpFactory(http: Http, injector: Injector, config: HttpConfig): return new HttpInterceptorService(http, injector, new URLRegExpInterceptorMatcher(), config.interceptors); } +export const HTTP_INTERCEPTOR_PROVIDER: Provider = { + provide: HttpInterceptorService, + useFactory: httpFactory, + deps: [Http, Injector, HTTP_CONFIG], +}; + @NgModule({ imports: [ HttpModule, @@ -24,11 +30,8 @@ export class CovalentHttpModule { providers: [{ provide: HTTP_CONFIG, useValue: config, - }, { - provide: HttpInterceptorService, - useFactory: httpFactory, - deps: [Http, Injector, HTTP_CONFIG], }, + HTTP_INTERCEPTOR_PROVIDER, ], }; }