This repository has been archived by the owner on Dec 26, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 96
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(docs): Add API and Testing documentation
- Loading branch information
1 parent
cddb9ae
commit 0dbff75
Showing
4 changed files
with
279 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
# @ngrx/effects API | ||
|
||
|
||
|
||
## EffectsModule | ||
|
||
Feature module for @ngrx/effects. | ||
|
||
### run | ||
|
||
Registers an effects class to be run immediately when the target module is | ||
created. Must be called multiple times for each effect class you want to run. | ||
|
||
Usage: | ||
```ts | ||
@NgModule({ | ||
imports: [ | ||
EffectsModule.run(SomeEffectsClass) | ||
] | ||
}) | ||
export class AppModule { } | ||
``` | ||
|
||
### runAfterBootstrap | ||
|
||
Registers an effects class to be run after root components are bootstrapped. | ||
Only works in the root module. Useful if your effects class requires components | ||
to be bootstrapped. | ||
|
||
If you are using a version of Angular older than 2.1, `runAfterBootstrap` is | ||
necessary for effects that inject services from `@angular/router`. | ||
|
||
Usage: | ||
```ts | ||
@NgModule({ | ||
imports: [ | ||
EffectsModule.runAfterBootstrap(SomeEffectsClass) | ||
] | ||
}) | ||
``` | ||
|
||
|
||
## Actions | ||
|
||
Stream of all actions dispatched in your application including actions | ||
dispatched by effect streams. | ||
|
||
### ofType | ||
|
||
Filter actions by action type. Accepts multiple action types. | ||
|
||
Usage: | ||
``` | ||
actions$.ofType('LOGIN', 'LOGOUT'); | ||
``` | ||
|
||
|
||
## Effect | ||
|
||
Decorator that marks a class property or method as an effect. Causes the | ||
decorated observable to be subscribed to `Store` when the effect class is | ||
ran. | ||
|
||
Usage: | ||
```ts | ||
class MyEffects { | ||
constructor(private actions$: Actions, private auth: AuthService) { } | ||
|
||
@Effect() login$: Observable<Actions> = this.actions$ | ||
.ofType('LOGIN') | ||
.switchMap(action => | ||
this.auth.login(action.payload) | ||
.map(res => ({ type: 'LOGIN_SUCCESS', payload: res })) | ||
.catch(err => Observable.of({ type: 'LOGIN_FAILURE', payload: err })) | ||
); | ||
|
||
@Effect() logout(): Observable<Actions> { | ||
return this.actions$ | ||
.ofType('LOGOUT') | ||
.switchMap(() => | ||
this.auth.logout() | ||
.map(res => ({ type: 'LOGOUT_SUCCESS', payload: res })) | ||
.catch(err => Observable.of({ type: 'LOGOUT_FAILURE', payload: err })) | ||
); | ||
} | ||
} | ||
``` | ||
|
||
Observables decorated with the `@Effect()` decorator are expected to be a stream | ||
of actions to be dispatched. Pass `{ dispatch: false }` to the decorator to | ||
prevent actions from being dispatched. | ||
|
||
Usage: | ||
```ts | ||
class MyEffects { | ||
constructor(private actions$: Actions) { } | ||
|
||
@Effect({ dispatch: false }) logActions$ = this.actions$ | ||
.do(action => { | ||
console.log(action); | ||
}); | ||
} | ||
``` | ||
|
||
## Utilities | ||
|
||
### toPayload | ||
Maps an action to its payload. | ||
|
||
Usage: | ||
```ts | ||
actions$.ofType('LOGIN').map(toPayload); | ||
``` | ||
|
||
### mergeEffects | ||
Manually merges all decorated effects into a combined observable. | ||
|
||
Usage: | ||
```ts | ||
export class MyService { | ||
constructor(effects: SomeEffectsClass) { | ||
mergeEffects(effects).subscribe(result => { | ||
|
||
}); | ||
} | ||
} | ||
``` | ||
|
||
## EffectsSubscription | ||
|
||
An rxjs subscription of all effects running for the current injector. Can be | ||
used to stop all running effects contained in the subscription. | ||
|
||
Usage: | ||
```ts | ||
class MyComponent { | ||
constructor(private subscription: EffectsSubscription) { } | ||
|
||
ngOnDestroy() { | ||
this.subscription.unsubscribe(); | ||
} | ||
} | ||
``` | ||
|
||
### addEffects | ||
Add additional instances of effect classes to the subscription. | ||
|
||
Usage: | ||
```ts | ||
class MyComponent { | ||
constructor(effects: MoreEffects, subscription: EffectsSubscription) { | ||
subscription.addEffects([ moreEffects ]); | ||
} | ||
} | ||
``` | ||
|
||
### parent | ||
A pointer to the parent subscription. Used to access an entire tree of | ||
subscriptions. | ||
|
||
Usage: | ||
```ts | ||
subscription.parent.unsubscribe(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Introduction | ||
|
||
## Effects | ||
In @ngrx/effects, effects are _sources of actions_. You use the `@Effect()` | ||
decorator to hint which observables on a service are action sources, and | ||
@ngrx/effects automatically merges your action streams letting you | ||
subscribe them to store. | ||
|
||
To help you compose new action sources, @ngrx/effects exports an `Actions` | ||
observable service that emits every action dispatched in your application. | ||
|
||
|
||
### Example | ||
1. Create an AuthEffects service that describes a source of login actions: | ||
```ts | ||
import { Injectable } from '@angular/core'; | ||
import { Http } from '@angular/http'; | ||
import { Actions, Effect } from '@ngrx/effects'; | ||
|
||
@Injectable() | ||
export class AuthEffects implements OnDestroy { | ||
constructor( | ||
private http: Http, | ||
private actions$: Actions | ||
) { } | ||
|
||
@Effect() login$ = this.actions$ | ||
// Listen for the 'LOGIN' action | ||
.ofType('LOGIN') | ||
// Map the payload into JSON to use as the request body | ||
.map(action => JSON.stringify(action.payload)) | ||
.switchMap(payload => this.http.post('/auth', payload) | ||
// If successful, dispatch success action with result | ||
.map(res => ({ type: 'LOGIN_SUCCESS', payload: res.json() })) | ||
// If request fails, dispatch failed action | ||
.catch(() => Observable.of({ type: 'LOGIN_FAILED' })); | ||
); | ||
} | ||
``` | ||
|
||
2. Provide your service via `EffectsModule.run` to automatically start your effect: | ||
```ts | ||
import { EffectsModule } from '@ngrx/effects'; | ||
import { AuthEffects } from './effects/auth'; | ||
|
||
@NgModule({ | ||
imports: [ | ||
EffectsModule.run(AuthEffects) | ||
] | ||
}) | ||
export class AppModule { } | ||
``` | ||
*Note*: For effects that depend on the application to be bootstrapped (i.e. | ||
effects that depend on the Router) use `EffectsModule.runAfterBootstrap`. Be | ||
aware that `runAfterBootstrap` will only work in the root module. | ||
|
||
|
||
### SystemJS Configuration | ||
@ngrx/effects is published with a UMD bundle. Map @ngrx/effects imports to the | ||
bundle: | ||
|
||
```ts | ||
System.config({ | ||
map: { | ||
'@ngrx/effects': 'npm:@ngrx/effects/bundles/effects.umd.js' | ||
} | ||
}) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Testing Effects | ||
|
||
1. Import the `EffectsTestingModule` in your testing module: | ||
```ts | ||
import { EffectsTestingModule, EffectsRunner } from '@ngrx/effects/testing'; | ||
|
||
describe('My Effect', () => { | ||
beforeEach(() => TestBed.configureTestingModule({ | ||
imports: [ | ||
EffectsTestingModule | ||
], | ||
declarations: [ | ||
AuthEffects | ||
] | ||
})); | ||
}); | ||
``` | ||
|
||
2. Inject the `EffectsTestRunner`: | ||
```ts | ||
let runner: EffectsRunner; | ||
|
||
beforeEach(inject([ | ||
EffectsRunner, | ||
(_runner) => { | ||
runner = _runner; | ||
} | ||
])); | ||
``` | ||
|
||
3. Queue up actions and then subscribe to the effect you want to test asserting | ||
on the result: | ||
```ts | ||
it('should return a LOGIN_SUCCESS action after logging in', () => { | ||
runner.queue({ type: 'LOGIN' }); | ||
|
||
authEffects.login$.subscribe(result => { | ||
expect(result).toEqual({ type: 'LOGIN_SUCCESS' }); | ||
}); | ||
}); | ||
``` |