From 8096171e08b091bc813e1f59511bba83298257d5 Mon Sep 17 00:00:00 2001 From: aokrushko Date: Wed, 22 May 2019 01:38:24 -0400 Subject: [PATCH] add docs --- .../content/guide/effects/lifecycle.md | 36 +++++++++++++++++++ .../ngrx.io/content/guide/effects/testing.md | 8 +++-- .../ngrx.io/content/guide/migration/v8.md | 8 +++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/projects/ngrx.io/content/guide/effects/lifecycle.md b/projects/ngrx.io/content/guide/effects/lifecycle.md index a54fab3183..28e021c4cd 100644 --- a/projects/ngrx.io/content/guide/effects/lifecycle.md +++ b/projects/ngrx.io/content/guide/effects/lifecycle.md @@ -14,6 +14,8 @@ init$ = createEffect(() => ); +## Effect Metadata + ### Non-dispatching Effects Sometimes you don't want effects to dispatch an action, for example when you only want to log or navigate based on an incoming action. But when an effect does not dispatch another action, the browser will crash because the effect is both 'subscribing' to and 'dispatching' the exact same action, causing an infinite loop. To prevent this, add `{ dispatch: false }` to the `createEffect` function as the second argument. @@ -36,6 +38,40 @@ export class LogEffects { } +### Resubscribe on Error + +Starting from NgRx V8 when error happens in the effect's main stream it is +reported using Angular's `ErrorHandler` and the source effect is +**automatically** resubscribe (instead of completeling), so it continues to +listen to any new dispatched Actions. + +Generally, errors should be handled by users and operators such as `mapToAction` +should make it easier to do. However, for the cases where errors were missed, +this new behavior adds additional safety net. + +In some cases where particular RxJS operators are used the new behavior might +produce unexpected results. For example, if the `startWith` operator is within +effect's pipe then it will be triggered again. + +To remove resubscriptions add `{resubscribeOnError: false}` to `createEffect` +metadata (second argument). + + +import { Injectable } from '@angular/core'; +import { Actions, Effect, ofType } from '@ngrx/effects'; +import { tap } from 'rxjs/operators'; + +@Injectable() +export class ErrorFreeEffects { + constructor(private actions$: Actions) {} + + disabledResubscriptionsActions$ = createEffect(() => + this.actions$.pipe( + tap(action => console.log(action)) + ), { resubscribeOnError: false }); +} + + ## Controlling Effects ### OnInitEffects diff --git a/projects/ngrx.io/content/guide/effects/testing.md b/projects/ngrx.io/content/guide/effects/testing.md index aa96719e00..e0ec80487d 100644 --- a/projects/ngrx.io/content/guide/effects/testing.md +++ b/projects/ngrx.io/content/guide/effects/testing.md @@ -119,11 +119,15 @@ describe('My Effects', () => { }); it('should register someSource$ that dispatches an action', () => { - expect(metadata.someSource$).toEqual({ dispatch: true }); + expect(metadata.someSource$).toEqual( + jasmine.objectContaining({ dispatch: true }) + ); }); it('should register someOtherSource$ that does not dispatch an action', () => { - expect(metadata.someOtherSource$).toEqual({ dispatch: false }); + expect(metadata.someOtherSource$).toEqual( + jasmine.objectContaining({ dispatch: false }) + ); }); it('should not register undecoratedSource$', () => { diff --git a/projects/ngrx.io/content/guide/migration/v8.md b/projects/ngrx.io/content/guide/migration/v8.md index bde77e0e7f..cf48cef7b4 100644 --- a/projects/ngrx.io/content/guide/migration/v8.md +++ b/projects/ngrx.io/content/guide/migration/v8.md @@ -146,6 +146,14 @@ export const getNews: MemoizedSelector = createSelector( ); ``` +### @ngrx/effects + +#### Resubscribe on Errors + +If error occurs (or it flattened into) main effect's pipe then it will be +reported and the effect is resubscribed automatically. In cases when this new behavior is +undesirable, it can be turned off with `{resubscribeOnError: false}` metadata +setting (for each effect individually). [Learn more](/guide/effects/lifecycle#resubscribe-on-error). ### @ngrx/router-store