Объединение операторов RxJS в новый оператор с помощью TypeScript
Я часто обнаруживаю, что добавляю одну и ту же последовательность операторов к наблюдаемым, например
observable$
.do(x => console.log('some text', x))
.publishReplay()
.refCount();
Я ищу способ объединить эти 3 оператора в небольшой многоразовый оператор (например, .cache('some text')), который я могу связать с любым наблюдаемым. Как я могу определить это в Typescript, чтобы я мог импортировать rxjs/Observable и этот оператор, как я делаю с операторами rxjs?2 ответа:
Чтобы реализовать описанный оператор, создайте файл
cache.tsследующего содержания: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; } }И потреблять его вот так:
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));
Ответ Картанта, приведенный выше, хорошо работает и отвечает на заданный вопрос.( Как я могу определить это в Typescript, чтобы я мог импортировать rxjs/Observable и этот оператор, как я делаю с операторами rxjs?)
Недавно я обнаружил оператор
let, который, если вам на самом деле не нужно, чтобы функция была реализована как оператор, все равно позволит вам высушить ваш код.Я начал внедрять услугу angular 2, чтобы интерфейс с моим бэкендом rails и знал, что большинство моих вызовов api будут выглядеть очень похоже, поэтому я хотел попробовать и поместить как можно больше общих вещей в функцию.
Почти все вызовы будут делать следующее:
- повторите попытку ошибки (моя функция ниже нуждается в дополнительной работе на этом фронте)
- отображение http-ответа в локально определенный класс typescript (через json-typescript-mapper )
- обрабатывать ошибки
Вот пример моего использования
letоператор для моих http-ответов через общую функцию (handleResponse)через оператор RxJS let.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})); }