RxJs——map,filter第二种实现

选中文字可对指定文章内容进行评论啦,绿色背景文字可以点击查看评论额。

上一节我们实现了map和filter函数,我们将这些函数都挂载在MyObservable对象上,这里存在一个问题,类似map和filter这样的操作型函数很多,所以不可能将他们都挂载在MyObservable对象上,因此,这里出现了第二种实现。

 

这些操作函数能串联起来的本质就是能够形成嵌套调用,因此我想到了使用pipe,pipe的本质是接收一个 RxJS 操作符的运行结果作为参数,并返回一个 Observable 实例。

代码实例

map实现

export function map(fn) {
    return (observable)=>{
        return new MyObservable(observer => {
            observable.subscribe({
                next: val=> observer.next(fn(val)),
                error: err => observer.error(err),
                complete: () => observer.complete()
            });
        });
    }
}

filter实现

export function filter(fn) {
    return (observable)=>{
        return new MyObservable(observer => {
            observable.subscribe({
                next: val=> fn(val)? observer.next(val): ()=>{},
                error: err => observer.error(err),
                complete: () => observer.complete()
            });
        });
    }
}

从这里我们可以看出 RxJS 操作符的运行结果就是map或者filter执行后的返回函数,返回值就是内部的一个MyObservable对象实例。

pipe单参数实现

pipe(operation) {
  return operation(this);
}

注意这里的this实际上就是对应函数中的(observable)这个参数。然后调用operation(this)后返回的是一个新的Observable,同时这个参数observable会执行subscribe方法,这个方法会将这些Observable串起来调用。

 

pipe多参数实现

pipe(...operations) {
    return operations.reduce((prev, fn) => fn(prev), this);
}

以上这个函数实现的具体功能就是形成一个函数嵌套调用,并且方向是从左向右的。

这个函数的实现最经典的算是在redux中的一段源码啦,有兴趣的可以看看这个框架,本身代码不多,但是阅读起来不容易理解,感兴趣的可以去看看。

下面我用测试代码验证下这个函数:

const letObservable = of(1,2,3);
const a = interval(500).pipe(map((v) => 'a' + v), take(3));
const b = interval(500).pipe(map((v) => 'b' + v), take(3));
letObservable.pipe(merge(a, b)).subscribe((value) => console.log(value));

日志信息如下:

这里我实现了另外的take和merge方法,调用情况可以知道和RxJs的效果一致。这里我也贴出他们的实现。

take实现

export function take(num) {
    return (observable) => (
      new MyObservable(observer => {
        let times = 0;
        let subscription = observable.subscribe({
          next: val => {
            times++;
            if (num >= times) {
              observer.next(val)
            } else {
              observer.complete()
              //if (subscription)subscription.unsubscribe()         
            }
          },
          error: err => observer.error(err),
          complete: () => observer.complete(),
        });
      })
    )
}

tap实现

export function tap(fn) {
    return (observable) => {
        return new MyObservable(observer => {
            observable.subscribe({
                next: val => {
                    fn(val);
                    observer.next(val);
                },
                error: err => observer.error(err),
                complete: () => observer.complete(),
            });
        });
    };
}

merge实现

export function merge(...observables) {
    return (observable) => {
        let completeNum = 0;
        if (observable) {
            observables = [observable,...observables];
        }
        return new MyObservable(observer => {
            observables.forEach(observable => {

                observable.subscribe({
                    next: val => observer.next(val),
                    error: err => {
                        observables.forEach(observable.unsubscribe);
                        observer.error(err)
                    } ,
                    complete: () => {
                        completeNum++;
                        if (completeNum === observables.length) {
                            observer.complete();
                        }
                        
                    },
                });
            });
        });
    };
}

好了,欢迎各位参与讨论。

 

 

版权声明:著作权归作者所有。

相关推荐

Java Objects.hash()与自己实现的hashCode()比较

Java 7新增了Objects类,它为对象提供了一些便捷的静态方法,如equals(),hashCode(),hash(),compare(),toString()等等。这里比较一下Objects.hash()与自己实现的hashCode()。传统实现的hashCode@Override public int hashCode() {  &nbs

Kotlin实现Java的三元条件运算

在Kotlin没有类似Java的三元条件运算:a ? b : c 在Kotlin有几种等效的方法:ifval r =if (a) b else c whenval r = when(a) {     true 

Pandas对应SQL的in和not in实现

在Pandas提供了pd.isin(),使用它可以实现SQL的in和not in。not in 对应于:~a.isin(b) 示例:假如有以下dataframe数据,它包含了列data如下:>>> df   data 0   a 1   b 2 &nb

Python switch语句的巧妙实现

在其他一些语言里,如Java,C等,它们提供了switch语句来根据提供的值返回不同的结果。而在python里是没有类似的语句。基本实现使用Python的字典可以很简单实现switch语句的功能。def f(x): return { 'a': 1, 'b': 2, }[x]switch的default值结合get()返回默认值:def f(x): re

IOS实现TouchID和FaceID

IOS TouchID或FaceID核心实现1.#import <LocalAuthentication/LocalAuthentication.h> 2.创建LAContext实例context3.配置context的localizedFallbackTitle,为验证失败后的撤销操作4.主要实现context的两个方法: (1)- (BOOL)canEvaluatePo

雪花算法实现-分布式系统

一、订单id的特殊性订单数据非常庞大,将来一定会做分库分表。那么这种情况下, 要保证id的唯一,就不能靠数据库自增,而是自己来实现算法,生成唯一id。二、雪花算法这里的订单id是通过一个工具类生成的,而工具类所采用的生成id算法,是由Twitter公司开源的snowflake(雪花)算法。三、简单原理雪花算法会生成一个64位的二进制数据,为一个Long型。(转换成字符串后长度最多19位) ,其基本

Java 8使用Collections toMap实现List转换为Map

Collections提供了toMap()来实现集合转换为Map。方法如下:Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) keyMapper:实现键的

C++队列缓存的实现

为什么使用队列缓存c++的队列缓存主要用于解决大数据量并发时的数据存储问题,可以将并发时的数据缓存到队列中,当数据量变小时再匀速写入硬盘中。 引用queue队列在头文件中引用queue队列#include <queue>using namespace std; 定义缓存结构体struct DataInfo{ char* pBuf;//缓存内容 int iSize;//缓存大小 D

Swift 4/5 实现GCD的dispatch_after

Swift 4实现延时的简单方法:DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { // Code}Swift 5实现延时的简单方法:DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: { // code to execute

Angular装饰器——两种实现方式

装饰器主要作用我们知道装饰器的两个主要作用1、在运行时更改对象的功能而不影响对象的现有功能2、将通用行为包装成简单,可复用的代码片段,减少模板代码的数量装饰器的定义我们首先看看定义:Decorators are functions called on classes, class elements, or other JavaScript syntax forms during definitio