rxjs拥有大量的操做符能够说基本涵括平常使用的方方面面, 但总有一天会有没有符合要求的操做符的一天, 或者, 即便有, 但咱们却没有找到, 毕竟已经存在的操做符已经不少了, 说不定会愈来愈多, 这时就须要咱们来自定义操做符了。html
本文针对 rxjs6 ,之前的版本能够查看 这篇文章。
在5.5版本, rxjs增长了pipe操做符, 在那以后, 自定义操做符的方式就很简单了, 基本就是实现一个函数, 官方文档中有以下描述:编程
基本上来讲,pipeable 操做符能够是任何函数,可是它须要返回签名为<T, R>(source: Observable<T>) => Observable<R>
的函数。
如今Observable
中有一个内置的pipe
方法 (Observable.prototype.pipe
),它能够用相似于以前的链式调用的方式来组合操做符
因此咱们只须要定义一个函数, 他的返回值签名是<T, R>(source: Observable<T>) => Observable<R>
就能够了。segmentfault
在使用一个例子开始之前,让咱们看看编写操做符的注意事项ide
接下来让咱们用一个简单的例子来实现如下函数式编程
假如咱们须要一个对数字进行平方的操做符:函数
square = () => { return source => { return source.pipe(map((value: number) => value * value)); }; }
他的入参为空, 返回的函数的行参source就是即将被传入的observable,
而后咱们就能够在,pipe()
中调用了学习
test() { const obs = of(1, 2, 3); // 1, 4, 9 obs.pipe(square()).subscribe((value) => console.log(value)); }
一个简单的操做符就完成了,但,是否是感受还少了些什么,对,要是传入进来的不是一个数字呢,那时用户会收到一个NaN(Not a Number)
, 因此,咱们还须要给他判断一下并报错ui
const square = () => source => source .pipe(map((value: number) => { // 判断传入的值是否为数字 if (value && !isNaN(value)) { return value * value; } throw Error('收到的数据不是数值类型'); }), catchError(err => of(err.toString())));
自定义操做符除了能够经过pipe()
进行,还有不少地方提到了lift()
这个方法, 而且不少地方都把 lift()
和pipe()
做为对比,因此又去学习了一下lift()
idea
建立一个新的Observable,以该Observable做为源,并将传递的运算符定义为新Observable的运算符。
它和pipe()
的对比能够查看这篇文章
简单的说spa
lift()建立一个新的可观察对象,但pipe()没有。pipe()遵循函数式编程范式,lift()是面向对象的。
(后面这部分感受理解的还不是很到位就不翻译了)
- pipe's operator function maps an Observable to an Observable
- lift's operator function maps an Observer to an Observer
This is just another way to represent the idea of either:
- building an Observable chain down from the source to the sink
- or building an Observer chain up from the sink to the source
rxjs
中lift()
如何使用呢, ,下面是一个简单的例子,改造后的square()
:
class Square implements Operator<number, number> { call(subscriber: Subscriber<number>, source: Observable<number>): void { source.subscribe(value => { if (value && !isNaN(value)) { subscriber.next(value * value); } throw Error('收到的数据不是数值类型'); }, error => console.log(error)); } }
使用
test() { const obs = of(123); obs.lift(new Square()).subscribe((value) => console.log(value)); // 1, 4, 9 }
上面只是一个简单的例子,若想经过lift()
编写操做符,能够直接参考那些操做符的源码, lift()
在源码中有大量的使用。
写完之后能明显的感受到这篇文章还有很大的改进空间,原本还想更细致探讨一下原理性的东西的,可是那一大堆花里胡哨的函数签名看的本身直发晕,并且如今汇报时间就要到了,仍是算了,等本身水平再提高一些了再来看吧。
Rxjs-自定义操做符
官方文档
What is the difference between Observable.lift and Observable.pipe in rxjs?