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