@ngry/rx
TypeScript icon, indicating that this package has built-in type declarations

16.1.0 • Public • Published

Description

RxJS toolkit for Angular development and testing.

Installation

Using NPM:

npm i @ngry/rx

Using Yarn:

yarn add @ngry/rx

Documentation

Table of contents:

Tasking

toTask operator

Use toTask operator to wrap original Observable<T> into the Observable<TaskState<T>>.

TaskState is an immutable structure that indicates async task's pending / complete / failed state and holds task result or error.

import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { TaskState, toTask } from '@ngry/rx';

export class ExampleService {
  constructor(private http: HttpClient) {
  }

  get(): Observable<TaskState<Entity>> {
    return this.http.get<Entity>('...').pipe(
      toTask(),
    );
  }
}

Then in your component:

import { Observable } from 'rxjs';
import { Component } from '@angular/core';
import { TaskState, takeTaskError, takeTaskResult } from '@ngry/rx';

@Component({
  selector: 'x-example',
  template: `
  <ng-container *ngIf="state$ | async as state">
    <p *ngIf="state.isPending()">Loading...</p>
    <pre *ngIf="state.isComplete()">{{ state.result | json }}</pre>
  </ng-container>
  `
})
export class ExampleComponment {
  readonly state$ = this.service.get();
  readonly result$ = this.state$.pipe(takeTaskResult());
  readonly error$ = this.state$.pipe(takeTaskError());

  constructor(
    private readonly service: ExampleService,
  ) {}
}

Filtering

ofType operator

Use ofType operator to filter values by certain type(s) (it uses instanceof operator to filter values stream).

export class Load {
  constructor(readonly id: number) {
  }
}

export class Loaded {
  constructor(readonly cart: Cart) {
  }
}

export class CartEffects extends EffectsProvider {
  constructor(
    actions: Actions,
    service: CartService,
  ) {
    super([
      actions.pipe(
        // 👇 Bypass only actions of type Load
        ofType(Load),
        switchMap(action => service.load(action.id)),
        map(cart => new Loaded(cart)),
      ),
    ]);
  }
}

dispatch operator

Use dispatch operator to control whether values must pass through this point of stream or not.

Open mode

from([1, 2, 3])
  .pipe(dispatch(true))
  .subscribe(console.log);
// Prints 1, 2, 3 then completes

Closed mode

from([1, 2, 3])
  .pipe(dispatch(false))
  .subscribe(console.log);
// Ignores values, thus prints nothing and completes

Testing

ObservableSpy

ObservableSpy tracks changes in Observable like emitted values, completion and failure for further analysis. Observables testing becomes easier.

Test emitted values:

import { from } from 'rxjs';
import { ObservableSpy } from '@ngry/rx';

test('emitted values', () => {
  const spy = new ObservableSpy<number>(from([1, 3, 5]));

  expect(spy.values).toEqual([1, 3, 5]);
});

Test completion:

import { empty } from 'rxjs';
import { ObservableSpy } from '@ngry/rx';

test('completion', () => {
  const spy = new ObservableSpy<number>(empty());

  expect(spy.complete).toBe(true);
});

Test error:

import { throwError } from 'rxjs';
import { ObservableSpy } from '@ngry/rx';

test('error', () => {
  const spy = new ObservableSpy<number>(throwError('Something went wrong'));

  expect(spy.error).toBe('Something went wrong');
});

License

MIT

Package Sidebar

Install

npm i @ngry/rx

Weekly Downloads

1

Version

16.1.0

License

none

Unpacked Size

73.9 kB

Total Files

25

Last publish

Collaborators

  • achugaev93