3

一.引言

RxJS提供了很多操作符对数据流(Observable)进行操作控制。例如map,tap,skip,fiter等等,总会忘记他们的作用是什么,感觉自己是时候总结一下他们了。

二. 什么是操作符?

操作符是 Observable 类型上的方法,比如 .map(...)、.filter(...)等等。
操作符是函数,它基于当前的 Observable 创建一个新的 Observable。当操作符被调用时,它们不会改变已经存在的 Observable 实例。相反,它们返回一个新的 Observable ,它的 subscription 逻辑基于第一个 Observable 。

!何时会使用Observable类型
Observable通常使用在异步操作中。

异步操作又分为两种:
1 进行网络请求
2 setTimeout()指定在一定时间后调用的函数的这一类函数。

三.认识弹珠图

Marble diagrams (弹珠图): 更好的理解操作符是如何工作的图表。
image.png
弹珠的时间是从左到右流动的,是一条时间轴。
image.png

四.动手实践

操作符有着不同的用途,它们可作如下分类:创建、转换、过滤、组合、错误处理、工具,等等
1.创建
from 从一个数组、类数组对象、Promise、迭代器对象或者类 Observable 对象创建一个 Observable.几乎可以把任何东西都能转化为Observable.
image.png

2.转换 输入和输出数量相等,值不等。
map 操作符 它把每个源值传递给转化函数以获得相应的输出值。
image.png
举个栗子:

import { Component } from '@angular/core';
import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  example:Observable<number> = from([1, 2, 20, 50])
  constructor() {
    this.example.pipe(map(v => v*2)).subscribe(
      data => console.log(data)
    )
  }
}

输出的结果:
image.png
:可以tap操作符做一下区分,tap操作符对源 Observable 上的每个发出值进行监听,做额外处理,但返回源相同的 Observable。输入和输出数量相等,值也相等。

3.过滤 输入数量大于等于输出数量相等。
举个例子:takeUntil
public takeUntil(notifier: Observable): Observable<T>
image.png
它发出源 Observable 的值,然后直到第二个 Observable (即 notifier )发出项,它便完成。
takeUntile一直过滤接受打出的Obervable值,知道接收到一个信号就停止就收了。
例子:

import { interval, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import {Component} from "@angular/core";
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  value = interval(1000)
  // 创建一个 Subject 作为停止条件
  stop = new Subject();

  // 创建一个 observable 每隔一秒发出一个值
  source = interval(1000);

  constructor() {
    // 使用 takeUntil 操作符,当 stopCondition$ 发出值时停止接收 source$ 的值
    const example = this.source.pipe(takeUntil(this.stop))
      .subscribe(v => {
        console.log(v)
      })

    setTimeout(() => {
      console.log('Stop信号');
      this.stop.next(1);
    }, 5000);
  }


}

4.组合
merge 将多个 observables 转换成单个 observable 。
public merge(other: ObservableInput, concurrent: number, scheduler: Scheduler): Observable
image.png
image.png
例子:

import { Component } from '@angular/core';
import {interval} from 'rxjs';
import { merge } from 'rxjs/operators';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  // 每2.5秒发出值
  first = interval(2500);
  
  // 每1秒发出值
  second = interval(1000);

  constructor() {
    const example = this.first.pipe(merge(this.second))
    example.subscribe(v => {
      console.log(v)
    })
  }
}

输出结果:
image.png

输出:
image.png

  1. 条件操作符
    find 只发出源 Observable 所发出的值中第一个满足条件的值。
    image.png
    例子
import { Component } from '@angular/core';
import {find, from} from 'rxjs';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  first = from([1, 2, 3, 4, 5])

  constructor() {
    const example = this.first.pipe(find(v => v % 2 === 0))
    example.subscribe(v => {
      console.log(v)
    })
  }
}

输出的结果:
image.png

pipe操作符,在上面的例子中,每个操作符都被当做pipe()的参数了,pipe()函数的作用是什么呢?
pipe 用于组合多个操作符 ,以对数据流进行处理。可以将一系列操作符作为参数传递给 pipe 方法,这些操作符将 依次 对数据流进行处理。这里的依次很关键,也代表着pipe()中组合的这么几个操作符的执行顺序就是从开始一直到结束的,其中的数据会同流水线一般在各个操作符中进行传递。上一个操作符把数据处理好了,会自动地把这个处理好的数据送给下一个操作符接收,基于这个在上一步处理过的数据再进行进一步的加工,如此往复,直到执行到最后一个操作符为止。
例子:

import { Component } from '@angular/core';
import {filter, find, from, interval, Observable, takeUntil} from 'rxjs';
import { merge } from 'rxjs/operators';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  first = from([1, 2, 3, 4, 5, 6]);
  second = from([10, 20, 30, 40 ,50])

  constructor() {
    const example = this.first.pipe(merge(this.second), filter(v => v % 2 === 0))
    example.subscribe(v => {
      console.log(v)
    })
  }
}

输出的结果:
image.png

总结
Rxjs中的操作符能够优雅的处理异步事件以及数据流,值得我们学习, 最后希望这边文章能够给您带来帮助。如有说得不对的地方,还望指正,谢谢!
官方文档:https://cn.rx.js.org/manual/overview.html#h213


吴季分
390 声望13 粉丝

引用和评论

0 条评论