使用TypeScript将RxJS运算符组合到新运算符中

时间:2017-02-03 22:48:55

标签: typescript rxjs rxjs5

我经常发现自己将相同的运算符序列添加到observables中,例如

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

我正在寻找一种方法将这三个运算符组合在一个可重复使用的小型运算符(例如.cache('some text'))中,我可以链接到任何可观察的运算符。如何在Typescript中定义它,以便我可以导入rxjs / Observable和这个运算符,就像我使用rxjs运算符一样?

2 个答案:

答案 0 :(得分:21)

要实现您所描述的运算符,请创建一个包含以下内容的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));

答案 1 :(得分:3)

Cartant上面的回答很有效,并且回答了问题( 如何在Typescript中定义它,这样我就可以像我一样导入rxjs / Observable和这个运算符使用rxjs运算符?

我最近发现了let运算符,如果您实际上不需要将该功能实现为 运算符 ,那么仍然会让您干掉你的代码。

我开始实现一个角度2服务来与我的rails后端接口,并且知道我的大多数api调用看起来非常相似,所以我想尝试在函数中放入尽可能多的常用内容。

几乎所有电话都会执行以下操作:

  1. 重试错误(我的函数下面需要更多工作)
  2. 将http响应映射到打字本地定义的类(通过json-typescript-mapper
  3. 处理错误
  4. 以下是我通过rxjs let运算符通过公共函数(handleResponse)将let运算符用于我的http响应的示例。

      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}));
      }