App下載

理解 Observables 在 JavaScript 編程中的重要性

超甜的布丁 2021-09-17 12:17:45 瀏覽數(shù) (2284)
反饋

The emitter Observable and the modulus Observable could be explicitly typed as follows: ?Reactive Extensions for JavaScript ?庫是專門用于事件處理的最強大和流行的 JavaScript 庫之一 ,或簡稱為 ?RxJS ?。 ?RxJS ?使用名為? Observable? 模式的四人組 ( GoF ) 設(shè)計模式作為注冊事件興趣的基礎(chǔ),以及在事件觸發(fā)時執(zhí)行某些操作。 下面,我們就一起來探索 ?RxJS ?庫的基礎(chǔ)知識以及它提供的 ?Observables? 的基本概念。

安裝 RxJS 庫

要開始討論 Observables, 我們首先安裝 RxJS 庫,如下所示: 

npm install rxjs 

 RxJS 庫已經(jīng)包括由 Typescript 所需的申報文件,所以沒有必要單獨使用?@types?安裝它們。 

要生成一個 Observable,我們可以使用 ?of?, 如下函數(shù): 

import { of, Observable } from "rxjs";  

const emitter : Observable<number> = of(1, 2, 3, 4); 

在這里,我們首先從?rxjs?庫中導(dǎo)入 ?of ?函數(shù)和 ?Observable?類型 。然后我們定義一個名為?emitter?的常量變量 ,它使用通用語法將其類型定義為類型?number?的 ?Observable  ?。然后我們將?of?函數(shù)的結(jié)果分配給 發(fā)射器變量,這將創(chuàng)建一個從數(shù)字 1 到 4 的 ?Observable?。我們現(xiàn)在可以創(chuàng)建一個 ?Observer?,如下所示: 

emitter.subscribe((value: number) => { 
    console.log(`value: ${value}`) 
}); 

在這里,我們調(diào)用變量?emitter?上的?subscribe?函數(shù)。由于 ?emitter? 變量是 ?Observable ?類型,它會自動公開 ?subscribe ?函數(shù)以注冊?Observers?。subscribe 函數(shù)將一個函數(shù)作為參數(shù),該函數(shù)將為 Observable 發(fā)出的每個值調(diào)用一次。這段代碼的輸出如下: 

value: 1 
value: 2 
value: 3 
value: 4 

在這里,我們可以看到我們傳遞給 subscribe 函數(shù)的函數(shù)確實為 Observable 發(fā)出的每個值調(diào)用了一次。 

請注意,只有在?Observable?上調(diào)用?subscribe ?函數(shù)時,?Observable ?才會開始發(fā)出值。調(diào)用該 ?subscribe ?函數(shù)稱為訂閱 ?Observable?,而 ?Observable ?產(chǎn)生的值也稱為 ?Observable ?流。 

?of? 函數(shù)有一個名為 ?from?的伙伴函數(shù),它使用一個數(shù)組作為 ?Observable ?的輸入,如下所示: 

const emitArray : Observable<number> = from([1, 2, 3, 4]); 
 
emitArray.subscribe((value: number) => { 
    console.log(`arr: ${value}`); 
}); 

在這里,我們有一個名為?emitArray?的變量 ,它的類型是 ?Observable<number>?,并且正在使用該 ?from ?函數(shù)從數(shù)組中創(chuàng)建一個 ?Observable?。同樣,我們對名為?emitArray? 的 ?Observable ?上調(diào)用?subscribe?函數(shù) ,并為 ?Observable ?發(fā)出的每個值提供一個要調(diào)用的函數(shù)。這段代碼的輸出如下: 

arr: 1 
arr: 2 
arr: 3 
arr: 4 

在這里,我們可以看到 ?from ?函數(shù)已經(jīng)從數(shù)組輸入創(chuàng)建了一個 ?Observable ?流,并且我們提供給 ?subscribe ?函數(shù)的函數(shù)正在為?Observable ?發(fā)出的每個值都調(diào)用一次。 

Pipe 和 Map 

RxJS 庫為所有的 ?Observable ?提供了一個 ?pipe ?函數(shù), 類似 ?subscribe ?函數(shù)。該 ?pipe函數(shù)將可變數(shù)量的函數(shù)作為參數(shù),并將對 ?Observable ?發(fā)出的每個值執(zhí)行這些函數(shù)。提供給 ?pipe ?函數(shù)的函數(shù)通常稱為 ?Observable ?操作符,它們都接受一個 ?Observable ?作為輸入,并返回一個 ?Observable ?作為輸出。 ?pipe ?函數(shù)發(fā)出一個 ?Observable ?流。 

這個概念最好通過閱讀一些代碼來解釋,如下例所示: 

import { map } from "rxjs/operators"; 
const emitter = of(1, 2, 3, 4); 
 
const modulus = emitter.pipe( 
    map((value: number) => { 
        console.log(`received : ${value}`); 
        return value % 2; 
    })); 
 
modulus.subscribe((value: number) => { 
    console.log(`modulus : ${value}`); 
}); 

在這里,我們從一個名為?emitter?的 ?Observable ?開始 ,它將發(fā)射值 1 到 4。然后我們定義一個名為?modulus ?的變量來保存對?emitter ???Observable??調(diào)用?pipe ?函數(shù)的結(jié)果 。我們?yōu)?pipe ?函數(shù)提供的的唯一參數(shù)是對?map ?函數(shù)的調(diào)用 ,它是 RxJS的運算符函數(shù)之一。 

?map ?函數(shù)將單個函數(shù)作為參數(shù),并將為 ?Observable ?發(fā)出的每個值調(diào)用此函數(shù)。該 ?map ?函數(shù)用于將一個值映射到另一個值,或以某種方式修改發(fā)出的值。在此示例中,我們返回將 2 的模數(shù)應(yīng)用于每個值的結(jié)果。 

最后,我們訂閱 ?Observable ?并將其值記錄到控制臺。這段代碼的輸出如下: 

received : 1 
modulus : 1 
received : 2 
modulus : 0 
received : 3 
modulus : 1 
received : 4 
modulus : 0 

在這里,我們可以看到 ?emitter Observable? 發(fā)出 1 到 4 的值,并且 ??modules Observable??正在為接收到的每個值發(fā)出的?Modules ?2。  

請注意,在這些代碼示例中,我們沒有明確設(shè)置 ?Observable ?的類型。 

?emitter Observable?和??modules Observable??可以顯式類型如下: 

const emitter : Observable<number> = of(1, 2, 3, 4); 
 
const modulus : Observable<number> = emitter.pipe(  
    ... 
); 

在這里,我們指定了 ?emitter Observable? 和??modules Observable ??的類型。這不是絕對必要的,因為 TypeScript 編譯器會在使用 ?Observables ?時確定正確的返回類型。然而,它確實明確說明了我們對 ?Observable ?流的期望,并且在更大或更復(fù)雜的 ?Observable ?轉(zhuǎn)換中,明確設(shè)置預(yù)期的返回類型使代碼更具可讀性并可以防止錯誤。 

組合運算符 

 ?pipe ?函數(shù)允許我們組合多個運算符函數(shù),每個函數(shù)都將應(yīng)用于 ?Observable ?發(fā)出的值??紤]以下代碼: 

const emitter = of(1, 2, 3, 4); 
 
const stringMap = emitter.pipe( 
    map((value: number) => { return value * 2 }), 
    map((value: number) => { return `str_${value}` }) 
); 
 
stringMap.subscribe((value: string) => { 
    console.log(`stringMap emitted : ${value}`); 
}); 

在這里,我們有一個?Observable?的命名 ?emitter? ,它將發(fā)射值 1 到 4。然后我們有一個名為?stringMap?的變量  ,用于保存 ?emitter Observable?的?pipe ?函數(shù)的結(jié)果 。在這個 ?pipe ?函數(shù)中,我們有兩個 ?map ?函數(shù)。第一個 ?map ?函數(shù)將傳入的數(shù)值乘以 2,第二個 ?map ?函數(shù)將其轉(zhuǎn)換為帶有前綴的字符串 str_。 

然后我們訂閱 Observable 并將每個值記錄到控制臺。這段代碼的輸出如下: 

stringMap emitted : str_2 
stringMap emitted : str_4 
stringMap emitted : str_6 
stringMap emitted : str_8 

在這里,我們可以看到兩個 ?map ?函數(shù)都應(yīng)用于?emitter Observable?發(fā)出的每個值 。請注意 ,在我們的第二個 ?map ?函數(shù)中,我們實際上已經(jīng)將每個值的類型從 ?number ?類型修改為 ?string ?類型。 這就是為什么在我們的函數(shù)中為?value ?參數(shù)指定 ?subscribe?的類型是 ?string? 類型的原因。 

概括 

在本篇文章中,我們已經(jīng)探討了基本的RxJS 庫,它提供了可觀測量的基本概念。我們已經(jīng)看到了如何使用 of 和 from 函數(shù)輕松創(chuàng)建 Observable  。


0 人點贊