Rxjs相關介紹

Rxjs簡單介紹

RxJS 是 Reactive Extensions for JavaScript 的縮寫。是一個基於可觀測數據流的響應式編程的庫。

它是基於訂閱-發佈模式觀察者模式迭代器實現的。

響應式編程

響應式編程是一種面向數據流和變化傳播的編程範式。這意味着可以在編程語言中很方便地表達靜態或動態的數據流,而相關的計算模型會自動將變化的值通過數據流進行傳播。 — 百度百科…

訂閱-發佈

項目中的 bus…

迭代器

所有的迭代器方法都必須有一個next方法,next返回{value: '', done: 'false || true'}

反過來說,實現next方法接口的數據對象都可以稱爲迭代器。

const arr = [1, 2, 3]
const iterator = arr[Symbol.iterator]()
iterator.next() // {value: 1, done: false}
iterator.next() // {value: 2, done: false}
iterator.next() // {value: 3, done: false}
iterator.next() // {value: 3, done: true}

核心概念

  1. Observable(可觀察對象)
  2. Observer (觀察者)
  3. subscriber (訂閱)
  4. Subject (Observable的特殊對象,繼承了Observable)
  5. operators(內部操作符)
Observable

可被觀察對象,提供三個方法

  • next
    返回一個值,觀察者可以接收到

  • error
    發佈一個異常的信號

  • complate
    發佈一個處理完成的信號

Observer

觀察者,支持三個回調

  • next
    處理被觀察者發佈的值
  • error
    處理被觀察者發佈的異常
  • complate
    處理被觀察者發佈完成的信號
subscriber

訂閱。將觀察者訂閱觀察被觀察者…

Subject

一個特殊的Observable實現,既可以做爲被觀察者又可以作爲觀察者。

因爲Observable被訂閱時,每一個訂閱它的都會獨立運行。

而subject則更像是一個真正的訂閱管理的維護者,它蒐集所有的訂閱者,統一發送給他們。有點類似於dom中的addEventListener

operators

rxjs內部的一些操作數據量的方法工具,比如創建、合併、過濾、轉換等等。

rxjs結合一些操作纔會顯得更加牛逼…

一些簡單的例子

// 使用create創建一個 observable
const source = rxjs.Observable.create(observable => {
	observable.next(1)
})

// 訂閱
source.subscribe(v => console.log(v))
// 1

等一下… 上面的代碼如果使用 Promise 寫的話…

const promise = function () {
	return new Promise(resolve => resolve(1))
}

promise.then(v => console.log(v))
// 1
// 看着差不多是不是...

但是問題恰恰在於,Promise 只能返回一次就完事了。

const source = rxjs.Observable.create(observable => {
	observable.next(1)
  observable.next(2)
})

// 訂閱
source.subscribe(v => console.log(v))
// 1
// 2

並且對於失敗後的處理,promise 失敗了結束了,需要主動去調用

getData () {} // ....
getData().catch(_ => {
	getData() // ...
})

// rxjs
const { interval, throwError, of } = rxjs
const { mergeMap, retry } = rxjs.operators
// interval 的意思是在指定時間給出一個累加的數字
const source = interval(1000).pipe(mergeMap(val => {
	if (val > 5) {
		return throwError('大於5了')
	}
	return of (val + 1)
}), retry(2)) // 這裏大於5後會拋出異常,但是又 retry 了2次

source.subscribe(v => console.log(v))
// 輸出 3遍 1 - 6,然後拋出異常

所以 promise 其實在處理異步中的問題並不是特別的完美。

對於觀察者中 errorcomplate的回調:

const source = rxjs.Observable.create(observable => {
	observable.next(1)
  observable.next(2)
  observable.complete()
})

source.subscribe({
  next (v) { 
    // ...
  },
  error () {
    // 處理錯誤情況... 
  },
  complete () {
    // 完成的情況...
  }
})

在一些場景中,往往是需要兩個數據接口組合在一起給視圖層的。顯然視圖層不適合做數據的組合的,這種情況下:

const a = rxjs.of({a: 1})
const b = rxjs.of({b: 2})
// 將數據流 a 與 b 組合在一起
const c =rxjs.combineLatest(a, b).pipe(rxjs.operators.map(([a, b]) => {
	return {...a, ...b}
}))

c.subscribe(v => console.log(v))
// {a: 1, b: 2}

過濾的場景:

const { interval } = rxjs
const { filter } = rxjs.operators
// 過濾可以整除2的數據
const source = interval(1000).pipe(filter(val => val % 2 === 0))

source.subscribe(v => console.log(v))
// 0 2 4 6 8...

還有其他一些操作符

  • first
  • last
  • take
  • delay
  • timeInterval

特別多,不在一一列舉,大概有100個左右?

詳情可以看下這裏https://rxjs.dev/guide/operators

場景分析

一個特別適合的例子,trello。

對於trello面板中展示的數據,可以考慮一下,他們是怎麼去規劃的,如何管理的數據流。

  1. 卡片的順序處理或者過濾條件
  2. 任務列表中卡片的數據組合(任務內容、標籤、相關人員等)
  3. 老數據與新數據的合併處理

這個過程可以反着推一下:

// 假如數據組合完畢了,只需要將數據單獨過濾然後再排序
const result = source.map(filter).map(sort)

// 假如新老數據已經合併完畢
const source = rxjs.combineLatest(task, label, users).pipe(map (...a) => {
		// 一堆合併操作
}) //組合數據

const task = rxjs.merge(oldtask, newtask) // 新舊的數據流合併到一起,對於下一層無感知是新還是舊
// label
// users

這樣的數據下一層對上一層的數據都是無感知的,不去關心你是新的還是就的,合併沒合併的,只需在數據流中向下走即可,最後result遍到了視圖層,直接渲染即可。

關於Scheduler

它相當於rxjs中的調度器,可以改變rx內部時間上的行爲。

調度器 目的
null 不傳遞任何調度器的話,會以同步遞歸的方式發送通知。用於定時操作或尾遞歸操作。
Rx.Scheduler.queue 當前事件幀中的隊列調度(蹦牀調度器)。用於迭代操作。
Rx.Scheduler.asap 微任務的隊列調度,它使用可用的最快速的傳輸機制,比如 Node.js 的 process.nextTick() 或 Web Worker 的 MessageChannel 或 setTimeout 或其他。用於異步轉換。
Rx.Scheduler.async 使用 setInterval 的調度。用於基於時間的操作符。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章