2017-02-03 1 views
10

Ich finde häufig, dass ich Observablen die gleiche Sequenz von Operatoren hinzufüge, z.Kombinieren von RxJS-Operatoren in einen neuen Operator unter Verwendung von TypScript

observable$ 
    .do(x => console.log('some text', x)) 
    .publishReplay() 
    .refCount(); 

ich nach einer Möglichkeit, diesen 3-Betreiber in einem kleinen wiederverwendbaren Operator (z .cache('some text')), dass ich kann Kette auf jede beobachtbare zu kombinieren. Wie kann ich dies in Typescript definieren, so dass ich rxjs/Observable und diesen Operator importieren kann, wie ich es mit rxjs-Operatoren mache?

Antwort

16

den Operator implementieren Sie beschrieben haben, erstellen Sie eine cache.ts-Datei mit folgendem Inhalt:

import { Observable } from "rxjs/Observable"; 
import "rxjs/add/operator/do"; 
import "rxjs/add/operator/publishReplay"; 

// Compose the operator: 

function cache<T>(this: Observable<T>, text: string): Observable<T> { 
    return this 
    .do(x => console.log(text, x)) 
    .publishReplay() 
    .refCount(); 
} 

// Add the operator to the Observable prototype: 

Observable.prototype.cache = cache; 

// Extend the TypeScript interface for Observable to include the operator: 

declare module "rxjs/Observable" { 
    interface Observable<T> { 
    cache: typeof cache; 
    } 
} 

Und verbrauchen sie dies wie:

import { Observable } from "rxjs/Observable"; 
import "rxjs/add/observable/of"; 
import "./cache"; 

let cached = Observable.of(1).cache("some text"); 
cached.subscribe(x => console.log(x)); 
+0

Ich hatte eine ähnliche Frage, das sieht nach einer guten Lösung aus. Da dies nur eine Kette von Operatoren ist, behandelt es Fehler und ist standardmäßig vollständig? Scheint so, als müsste es, aber ich bin neu bei rxjs. – nPn

+0

@nPn Ja, Fehler und Vervollständigungen werden von den Abonnenten des zusammengesetzten Observablen empfangen. Hier muss nichts getan werden. – cartant

+0

Wenn ich diesen Ansatz versuche, bekomme ich diesen Fehler: "EXCEPTION: Uncaught (in Versprechen): Fehler: Fehler in der ./DashboardComponent Klasse DashboardComponent - Inline-Vorlage: 2: 4 verursacht durch: __WEBPACK_IMPORTED_MODULE_2_rxjs_Observable __. Observable.of (...) .restrictToCommand ist keine Funktion TypeError: __WEBPACK_IMPORTED_MODULE_2_rxjs_Observable __. Observable.of (...). restrictToCommand ist keine Funktion. Irgendwelche Ideen? –

2

Antwort über die cartant funktioniert gut und beantwortet die Frage, die gestellt wurde (Wie kann ich das in Typescript definieren, so dass ich rxjs/Observable und diesen Operator wie ich mit rxjs Operatoren importieren konnte?)

Ich entdeckte vor kurzem die let Operator, wenn Sie nicht brauchen, tatsächlich die Funktion als Operator implementiert haben, noch lassen Sie Ihren Code vertrocknen.

Ich begann mit der Implementierung eines eckigen 2-Dienstes zur Schnittstelle mit meinem Rails-Backend und wusste, dass die meisten meiner API-Aufrufe sehr ähnlich aussehen würden, also wollte ich versuchen, so viel wie möglich in eine Funktion zu bringen.

Fast alle Anrufe in die folgenden tun:

  1. Wiederholungs auf einem Fehler (meine Funktion muss weiter unten noch mehr Arbeit an dieser Front)
  2. die HTTP-Antwort in eine Typoskript Karte Klasse lokal definiert (via json-typescript-mapper)
  3. Griff Fehler

Hier ist ein Beispiel für meine Verwendung des let Operator meiner hTTP-Antworten durch eine gemeinsame Funktion (Hand leResponse) über den rxjs-Operator.

handleResponse<T>({klass, retries=0} :{klass:any,retries?:number }) : (source: Observable<Response>) => Observable<T> { 
    return (source: Observable<Response>) : Observable<T> => { 
     return source.retry(retries) 
      .map((res) => this.processResponse(klass,res)) 
      .catch((res) => this.handleError(res)); 
    } 
    } 

    processResponse(klass, response: Response) { 
    return deserialize(klass, response.json()); 
    } 

    handleError(res: Response) { 
    const error = new RailsBackendError(res.status, res.statusText); 
    return Observable.throw(error); 
    } 

    getUserList({page=1,perPage=30,retry=0}: { page?:number, perPage?:number, retry?:number }={}) : Observable<UserList> { 
    const requestURL = `/api/v1/users/?${this.apiTokenQueryString}&page=${page}&per_page=${perPage}`; 
    return this.http.get(requestURL).let(this.handleResponse<UserList>({klass: UserList})); 
    } 
Verwandte Themen