欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

RxJS入门 有大用

  1. 简介

  • Observable:可观察者,表示未来有值或事件的可调用集合的概念,其实就是定义一个懒加载的函数对象,可以稍后被调用也可以不被调用,在调用的时候将会生产数据。

  • Observer:观察者,它是一个回调的集合,所以它监听了Observable传递的值并且可以做处理,其实就是用于消费Observable生产的数据。

  • Subscription:订阅或者消费,表示Observable的执行,当订阅了一个Observable后将返回Subscription对象,此对象主要用于取消订阅。

  • Operators:操作函数,可以使用函数式编程风格来处理具有map、filter、concat、reduce等操作的集合。(回头再补充)

  • Subject:主题,相当于事件发送者(EventEmitter),也是将一个值或者事件传播到多个Observable的唯一方式(其实就是Observable的多播实现方式)

  • Schedulers:调度者,是控制并发的集中调度程序,当发生像setTimeout、requestAnimationFrame等其他计算的时候允许我们进行协调。

  1. RxJS英文全称是Reactive Extensions for JavaScript,响应式扩展的js;是一个使用可观察序列编写异步和事件程序的库。

  2. ReactiveX将观察者模式、迭代器模式、函数式编程和集合相结合,以便满足对管理事件序列的一种理想方式。

  3. RxJS解决异步事件管理的基本概念如下:

  • Observable

    • Function是一种延迟计算的计算,它在调用时同步返回单个值。

    • Iterator是一种延迟计算的计算,它在迭代时同步返回零到(可能)无限值。

    • Promise是一种可能(或可能不会)最终返回单个值的计算。

    • Observable是一种延迟计算的计算,从它被调用的那一刻起,它可以同步或异步返回零到(可能)无限值。

    • 当你订阅时,你会得到一个订阅,它代表正在进行的执行。只需调用unsubscribe()即可取消执行

    • 当我们使用创建 Observable 时,每个 Observable 都必须定义如何处理该执行的资源create();您可以通过unsubscribe从内部返回自定义函数来做到这一点function subscribe()

      例如,这是我们清除间隔执行集的方式setInterval

    • 查看代码
      const observable = new Observable(function subscribe(subscriber) {
        // Keep track of the interval resource
        const intervalId = setInterval(() => {
          subscriber.next('hi');
        }, 1000);
      
        // 提供一种取消和处理interval资源的方法
        return function unsubscribe() {
          clearInterval(intervalId);
        };
      });
      // 执行订阅
      const unsubscribe = observable.subscribe(x => console.log(x));
      
      // 在两秒以后取消订阅,将会调用上面重写的unsubscribe方法来停止hi的输出并且清楚interval资源
      setTimeout(() => {
        unsubscribe.unsubscribe();
      }, 2000);
    • 创建描述中的Subscribe其实代表的就是Observable的execution

    • Execution可以传递三种类型的值:

    • next是最重要的,支持无限个next的执行,必须要实现;而error和complete如果触发的话那么只会触发其中一个方法,因为如果异常了,那么就不会到complete中,如果到了complete中那么肯定没发生异常

    • Observable严格按照Observable契约,所以在complete以后是不会再执行next的,如下:

    • 查看代码
      import { Observable } from 'rxjs';
      
      const observable = new Observable(function subscribe(subscriber) {
        subscriber.next(1);
        subscriber.next(2);
        subscriber.next(3);
        subscriber.complete();
        subscriber.next(4); // 此处将不会被执行,因为在这前面以后调用了complete方法
      });
    • 我们可以在Subscribe函数中进行try-catch,有效的捕捉异常,如下:

    • 查看代码
      import { Observable } from 'rxjs';
      
      const observable = new Observable(function subscribe(subscriber) {
        try {
          subscriber.next(1);
          subscriber.next(2);
          subscriber.next(3);
          subscriber.complete();
        } catch (err) {
          subscriber.error(err); // 观察者中任意位置发生了异常都会执行此回调函数
        }
      });
    • next:发送数值、字符串、对象等。

    • error:发送JavaScript的错误或者异常。

    • complete:不发送值,仅作为正常完成后的自定义处理。

    • 可以使用如下方式对上面创建的Observable进行订阅:

    • 查看代码
      observable.subscribe(x => console.log(x));
    • 订阅一个Observable对象就像调用一个函数,产生的数据将会被回传到回调函数中(Subscribe函数)

    • 使用Subscribe函数作为参数的方式创建Observable,如下(其他方式在Observer介绍中说明)创建了一个Observable对象,在被订阅后将每秒发送一个hi的字符给消费者:

    • 查看代码
      import { Observable } from 'rxjs';
      
      const observable = new Observable(function subscribe(subscriber) {
        const id = setInterval(() => {
          subscriber.next('hi')
        }, 1000);
      });
    • Observable可以使用new的方式创建,最常见的方式应该是使用of、from、interval、httpClient请求等方式

    • 查看代码
      import { Observable } from 'rxjs';
      
      const foo = new Observable(subscriber => {
        console.log('Hello');
        subscriber.next(42);
        subscriber.next(100); // "return" another value
        subscriber.next(200); // "return" yet another
      });
      
      console.log('before');
      foo.subscribe(x => {
        console.log(x);
      });
      console.log('after');
    • 输出结果如下:

    • 查看代码
      "before"
      "Hello"
      42
      100
      200
      "after"

       

    • 同步调用普通方法如下:

    • 查看代码
      function foo() {
        console.log('Hello');
        return 42;
      }
      
      console.log('before');
      console.log(foo.call());
      console.log('after');
    • 输出结果如下:

    • 查看代码
      "before"
      "Hello"
      42
      "after"
    • 使用Observable执行如下:

    • 查看代码
      const foo = new Observable(subscriber => {
        console.log('Hello');
        subscriber.next(42);
      });
      console.log('before');
      foo.subscribe(x => {
        console.log(x);
      });
      console.log('after');
    • 输出结果如下:

    • 查看代码
      "before"
      "Hello"
      42
      "after"
    • 在Pull系统中,消费者将确定什么时候获取生产者的数据,生产者本身不知道何时将会被数据给消费者,像Function这种,只有当被调用的时候才会产生数据,又或者像Iterator,只有调用其next方法的时候才会产生数据

    • 在Push系统中,生产者决定何时向消费者发送数据,消费者不知道何时会收到该数据,一般都是使用回调的方式来实现被动消费

    • 惰性代表是懒加载,定义好的Observable并不会被立即执行,如下:

    • 查看代码
      import { Observable } from 'rxjs';
      
      const observable = new Observable(subscriber => {
        subscriber.next(1);
        subscriber.next(2);
        setTimeout(() => {
          subscriber.next(3);
          subscriber.complete();
        }, 1000);
      });
    • 只有当订阅了此Observable才会被调用,如下:

    • 查看代码
      import { Observable } from 'rxjs';
      
      const observable = new Observable(subscriber => {
        subscriber.next(1);
        subscriber.next(2);
        setTimeout(() => {
          subscriber.next(3);
          subscriber.complete();
        }, 1000);
      });
      
      console.log('just before subscribe');
      observable.subscribe({
        next(x) { console.log('got value ' + x); },
        error(err) { console.error('something wrong occurred: ' + err); },
        complete() { console.log('done'); }
      });
      console.log('just after subscribe');
    • 在控制台上执行如下:

    • 查看代码
      just before subscribe
      got value 1
      got value 2
      just after subscribe
      got value 3
      done
    1. 可观察者是多个值的惰性Push集合,常见的Pull对象有Function、Iterator,Promise是单值的Push

    2. Pull和Push是两种不同的协议,用于描述生产者与消费者如何通讯的方式,说白了,Pull就是消费者主动去要数据,Push就是消费者被动接收数据(类似于等待生产者告诉你有数据了你才会去消费)。

    3. Observable是同步执行的,只不过它也支持异步(比如说Http请求或者定时器)

    4. Observables 可以随着时间的推移“返回”多个值,但是Function不可能进行多次return

    5. 创建

    6. 订阅

    7. 执行

    8. 取消

    9.  与其他类型的比较

  • Observer

    • 查看代码
      // 定义一个用于消费的observer
      const observer = {
        next: x => console.log('Observer got a next value: ' + x),
        error: err => console.error('Observer got an error: ' + err),
        complete: () => console.log('Observer got a complete notification'),
      };
      
      // 对observable进行订阅的时候将observer传入进行,用于消费数据
      observable.subscribe(observer);
      
      // 也可以使用简单的方式,不用传入observer对象,只需要传入一个回调函数就行
      observable.subscribe(x => console.log('Observer got a next value: ' + x));
    1. Observer 是 Observable 的消费者(Observable会生产数据,Observer对这些数据进行消费)。观察者只是一组回调,对应于 Observable 传递的每种类型的通知:nexterrorcomplete。下面是一个典型的 Observer 对象的例子:

  • Operators

    • 有时候我们想把多个运算符写到一个方法里面,方便去重用或者方便定义,那可以使用pipe来实现(这个pipe和observable上的pipe名字一模一样,官方也没解释为什么这样命名),如下:

    • 查看代码
      import { pipe } from 'rxjs';
      import { filter, map } from 'rxjs/operators';
      
      discardOddDoubleEven() {
        return pipe(
          filter<number>((v) => !(v % 2)),
          map((v) => v + v)
        );
      }
      
      of(1, 2, 3)
      .pipe(this.discardOddDoubleEven())
      .subscribe((v) => console.log(`value: ${v}`));
      
      // 创建一个只对偶数值就行翻倍的函数
      
      // Logs: 4
    • 查看代码
      import { of } from 'rxjs';
      import { map } from 'rxjs/operators';
      
      of(1, 2, 3)
        .pipe(map((x) => x * x))
        .subscribe((v) => console.log(`value: ${v}`));
      // Logs:
      // value: 1
      // value: 4
      // value: 9
    • 管道操作符主要是将第一个Observable作为参数输入并且返回一个新的Observable,但是其订阅逻辑是基于第一个Observable

    • 创建操作符主要是以独立函数的方式创建新的Observable

    1. Operator是一种基于Observable实例进行运算的函数,比如说过滤、合并、求平方...

    2. Operator分两种,一种是管道操作符,一种是创建操作符

    3. 使用创建操作符创建一个新的Observable并且使用管道操作符进行求平方的运算,如下代码:

    4. 上述代码中使用of创建一个新的Observable,并且使用map来对每一个值进行求平方,注意,在of后面使用了pipe方法,主要是因为operator就是普通的函数,可以被连续调用,所以如果有多个operator被调用,其代码就会变得可读性很差,比如说of(1,2,3).op4()(op3()(op2()(op1()(obs)))),所以使用pipe方式就是为了使其更具有可读性。

    5. 使用pipe()函数生成新的操作符

    6. Rxjs提供的运算符很多,这里就不赘述了,请查看官网,按需使用:Rxjs操作符

  • Subscription

    • 查看代码
    • 查看代码
    1. Subscription 是一个表示一次性资源的对象,对Observable的执行会返回一个Subscription对象,此对象有一个重要的无参方法unsubscribe,它是指取消订阅,我们可以在此方法中释放自己需要释放的资源,如下:

    2.  Subscription可以添加ChildSubscription,并且在Subscription调用unsubscribe方法以后将ChildSubscription也一并取消了,如下:

  • Subject

    1. 主题主要是用于多播场景,等用到的时候或者时间充足的时候再来记录吧,请查看官网:主题

  • Schedulers

    1. 调度器这个可能涉及到原理,等深入去玩Angular的时候再来记录吧,请查看官网:调度器


    来自 https://www.cnblogs.com/moon-demon/p/15978109.html


    普通分类: