Skip to content

Commit

Permalink
feat(effects): add provideEffects function
Browse files Browse the repository at this point in the history
  • Loading branch information
markostanimirovic committed Aug 12, 2022
1 parent 53cb0ca commit a011fe6
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 33 deletions.
2 changes: 1 addition & 1 deletion modules/effects/spec/effects_root_module.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { TestBed } from '@angular/core/testing';
import { INIT, Store, StoreModule } from '@ngrx/store';

import { EffectsModule } from '../src/effects_module';
import { ROOT_EFFECTS_INIT } from '../src/effects_root_module';
import { ROOT_EFFECTS_INIT } from '../src/effects_actions';

describe('Effects Root Module', () => {
const foo = 'foo';
Expand Down
2 changes: 1 addition & 1 deletion modules/effects/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { Observable, OperatorFunction, Operator } from 'rxjs';
import { filter } from 'rxjs/operators';

@Injectable()
@Injectable({ providedIn: 'root' })
export class Actions<V = Action> extends Observable<V> {
constructor(@Inject(ScannedActionsSubject) source?: Observable<V>) {
super();
Expand Down
2 changes: 1 addition & 1 deletion modules/effects/src/effect_sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
import { EFFECTS_ERROR_HANDLER } from './tokens';
import { getSourceForInstance, ObservableNotification } from './utils';

@Injectable()
@Injectable({ providedIn: 'root' })
export class EffectSources extends Subject<any> {
constructor(
private errorHandler: ErrorHandler,
Expand Down
4 changes: 4 additions & 0 deletions modules/effects/src/effects_actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { createAction } from '@ngrx/store';

export const ROOT_EFFECTS_INIT = '@ngrx/effects/init';
export const rootEffectsInit = createAction(ROOT_EFFECTS_INIT);
11 changes: 0 additions & 11 deletions modules/effects/src/effects_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ import {
SkipSelf,
Type,
} from '@angular/core';
import { Actions } from './actions';
import { EffectSources } from './effect_sources';
import { EffectsFeatureModule } from './effects_feature_module';
import { defaultEffectsErrorHandler } from './effects_error_handler';
import { EffectsRootModule } from './effects_root_module';
import { EffectsRunner } from './effects_runner';
import {
_FEATURE_EFFECTS,
_ROOT_EFFECTS,
_ROOT_EFFECTS_GUARD,
EFFECTS_ERROR_HANDLER,
FEATURE_EFFECTS,
ROOT_EFFECTS,
USER_PROVIDED_EFFECTS,
Expand Down Expand Up @@ -58,13 +54,6 @@ export class EffectsModule {
return {
ngModule: EffectsRootModule,
providers: [
{
provide: EFFECTS_ERROR_HANDLER,
useValue: defaultEffectsErrorHandler,
},
EffectsRunner,
EffectSources,
Actions,
rootEffects,
{
provide: _ROOT_EFFECTS,
Expand Down
12 changes: 2 additions & 10 deletions modules/effects/src/effects_root_module.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import { NgModule, Inject, Optional } from '@angular/core';
import {
createAction,
StoreModule,
Store,
StoreRootModule,
StoreFeatureModule,
} from '@ngrx/store';
import { Store, StoreRootModule, StoreFeatureModule } from '@ngrx/store';
import { EffectsRunner } from './effects_runner';
import { EffectSources } from './effect_sources';
import { ROOT_EFFECTS, _ROOT_EFFECTS_GUARD } from './tokens';

export const ROOT_EFFECTS_INIT = '@ngrx/effects/init';
export const rootEffectsInit = createAction(ROOT_EFFECTS_INIT);
import { ROOT_EFFECTS_INIT } from './effects_actions';

@NgModule({})
export class EffectsRootModule {
Expand Down
6 changes: 5 additions & 1 deletion modules/effects/src/effects_runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import { Subscription } from 'rxjs';

import { EffectSources } from './effect_sources';

@Injectable()
@Injectable({ providedIn: 'root' })
export class EffectsRunner implements OnDestroy {
private effectsSubscription: Subscription | null = null;

get isStarted(): boolean {
return !!this.effectsSubscription;
}

constructor(
private effectSources: EffectSources,
private store: Store<any>
Expand Down
8 changes: 3 additions & 5 deletions modules/effects/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@ export { EffectsMetadata, CreateEffectMetadata } from './models';
export { Actions, ofType } from './actions';
export { EffectsModule } from './effects_module';
export { EffectSources } from './effect_sources';
export { ROOT_EFFECTS_INIT, rootEffectsInit } from './effects_actions';
export { EffectsRunner } from './effects_runner';
export { EffectNotification } from './effect_notification';
export { EffectsFeatureModule } from './effects_feature_module';
export {
ROOT_EFFECTS_INIT,
rootEffectsInit,
EffectsRootModule,
} from './effects_root_module';
export { EffectsRootModule } from './effects_root_module';
export { EFFECTS_ERROR_HANDLER } from './tokens';
export { act } from './act';
export {
Expand All @@ -28,3 +25,4 @@ export {
} from './lifecycle_hooks';
export { USER_PROVIDED_EFFECTS } from './tokens';
export { concatLatestFrom } from './concat_latest_from';
export { provideEffects } from './provide_effects';
64 changes: 64 additions & 0 deletions modules/effects/src/provide_effects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { ENVIRONMENT_INITIALIZER, inject, Provider, Type } from '@angular/core';
import { Store } from '@ngrx/store';
import { EffectsRunner } from './effects_runner';
import { EffectSources } from './effect_sources';
import { rootEffectsInit as effectsInit } from './effects_actions';

/**
* Runs provided effects. Can be called at the root or feature level.
* Unlike the `StoreModule.forRoot` method, this function does not need
* to be called at the root level if there are no root effects.
*
* @usageNotes
*
* ### Providing root effects
*
* ```ts
* bootstrapApplication(AppComponent, {
* providers: [provideEffects([RouterEffects])],
* });
* ```
*
* ### Providing feature effects
*
* ```ts
* const booksRoutes: Route[] = [
* {
* path: '',
* providers: [provideEffects([BooksApiEffects])],
* children: [
* { path: '', component: BookListComponent },
* { path: ':id', component: BookDetailsComponent },
* ],
* },
* ];
* ```
*/
export function provideEffects(effects: Type<unknown>[]): Provider[] {
return [
effects,
{
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useValue: () => {
const effectsRunner = inject(EffectsRunner);
const effectSources = inject(EffectSources);
const shouldInitEffects = !effectsRunner.isStarted;

if (shouldInitEffects) {
effectsRunner.start();
}

for (const effectsClass of effects) {
const effectsInstance = inject(effectsClass);
effectSources.addEffects(effectsInstance);
}

if (shouldInitEffects) {
const store = inject(Store);
store.dispatch(effectsInit());
}
},
},
];
}
8 changes: 6 additions & 2 deletions modules/effects/src/tokens.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { InjectionToken, Type } from '@angular/core';
import { EffectsErrorHandler } from './effects_error_handler';
import {
defaultEffectsErrorHandler,
EffectsErrorHandler,
} from './effects_error_handler';

export const _ROOT_EFFECTS_GUARD = new InjectionToken<void>(
'@ngrx/effects Internal Root Guard'
Expand All @@ -20,5 +23,6 @@ export const FEATURE_EFFECTS = new InjectionToken<any[][]>(
'@ngrx/effects Feature Effects'
);
export const EFFECTS_ERROR_HANDLER = new InjectionToken<EffectsErrorHandler>(
'@ngrx/effects Effects Error Handler'
'@ngrx/effects Effects Error Handler',
{ providedIn: 'root', factory: () => defaultEffectsErrorHandler }
);
2 changes: 1 addition & 1 deletion modules/store/src/scanned_actions_subject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Subject } from 'rxjs';

import { Action } from './models';

@Injectable()
@Injectable({ providedIn: 'root' })
export class ScannedActionsSubject
extends Subject<Action>
implements OnDestroy
Expand Down

0 comments on commit a011fe6

Please sign in to comment.