Stories

Detail Return Return

Rxjs 常用操作符總結 - Stories Detail

一.引言

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

Add a new Comments

Some HTML is okay.