小編給大家分享一下Angular中RxJS怎么映射數(shù)據(jù),相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創(chuàng)新互聯(lián)主要從事網(wǎng)站設計制作、做網(wǎng)站、網(wǎng)頁設計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務銅山,10年網(wǎng)站建設經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:18980820575
Map
數(shù)據(jù)是程序開發(fā)時的一種常見操作。當在代碼中使用RxJS
來生成數(shù)據(jù)流時,很可能最終需要一種方法來將數(shù)據(jù)映射成需要的任何格式。RxJS
提供了常規(guī)的 map
函數(shù),還有 mergeMap
、switchMap
和concatMap
這樣的函數(shù),它們的處理方式略有不同。
map
操作符是最常見的。對于Observable
發(fā)出的每個值,都可以應用一個函數(shù)來修改數(shù)據(jù)。返回值將在后臺被重新釋放為Observable
,這樣就可以在流中繼續(xù)使用它。它的工作原理與在數(shù)組中使用它的方法非常相似。
不同之處在于,數(shù)組將始終只是數(shù)組,而在映射時,將獲得數(shù)組中當前的索引值。對于observable
,數(shù)據(jù)的類型可以是各種類型。這意味著可能需要在 Observable map
函數(shù)中做一些額外的操作來獲得想要的結果??聪旅娴睦樱?
import { of } from "rxjs"; import { map } from "rxjs/operators"; // 創(chuàng)建數(shù)據(jù) const data = of([ { brand: "保時捷", model: "911" }, { brand: "保時捷", model: "macan" }, { brand: "法拉利", model: "458" }, { brand: "蘭博基尼", model: "urus" } ]); // 按照brand model的格式輸出,結果:["保時捷 911", "保時捷 macan", "法拉利 458", "蘭博基尼 urus"] data.pipe(map(cars => cars.map(car => `${car.brand} ${car.model}`))).subscribe(cars => console.log(cars)); // 過濾數(shù)據(jù),只保留brand為porsche的數(shù)據(jù),結果:[{"brand":"保時捷","model":"911"},{"brand":"保時捷","model":"macan"}] data.pipe(map(cars => cars.filter(car => car.brand === "保時捷"))).subscribe(cars => console.log(cars));
首先用一系列汽車創(chuàng)建了可觀察對象。然后訂閱這個可觀測值2次。
第一次修改數(shù)據(jù)時,得到了一個由brand
和model
字符串連接起來的數(shù)組。
第二次修改數(shù)據(jù)時,得到了一個只有brand
為保時捷
的數(shù)組。
在這兩個例子中,使用Observable
map操作符來修改由Observable
發(fā)出的數(shù)據(jù)。返回修改的結果,然后map
操作符將結果封裝到一個可觀察對象中,以便后面可以subscribe
。
現(xiàn)在假設有這樣一個場景,有一個可觀察到的對象,它發(fā)出一個數(shù)組,對于數(shù)組中的每一項,都需要從服務器獲取數(shù)據(jù)。
可以通過訂閱數(shù)組來做到這一點,然后設置一個映射來調(diào)用一個處理API調(diào)用的函數(shù),訂閱其結果。如下:
import { of, from } from "rxjs"; import { map, delay } from "rxjs/operators"; const getData = param => { return of(`檢索參數(shù): ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => console.log(val));
map
函數(shù)返回getData
函數(shù)的值。在這種情況下,這是可觀測的。但這產(chǎn)生了一個問題:因為現(xiàn)在要處理一個額外的可觀測值。
為了進一步闡明這一點:from([1,2,3,4])
作為“外部”可觀察對象,getData()
的結果作為“內(nèi)部”可觀察對象。從理論上講,必須同時接受外部和內(nèi)部的可觀測數(shù)據(jù)??梢允沁@樣的:
import { of, from } from "rxjs"; import { map, delay } from "rxjs/operators"; const getData = param => { return of(`檢索參數(shù): ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log(data)));
可以想象,這與必須調(diào)用Subscribe
兩次的理想情況相去甚遠。這就是mergeMap
發(fā)揮作用的地方。MergeMap
本質上是mergeAll
和map
的組合。MergeAll
負責訂閱“內(nèi)部”可觀察對象,當MergeAll
將“內(nèi)部”可觀察對象的值合并為“外部”可觀察對象時,不再需要訂閱兩次。如下:
import { of, from } from "rxjs"; import { map, delay, mergeAll } from "rxjs/operators"; const getData = param => { return of(`檢索參數(shù): ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe( map(param => getData(param)), mergeAll() ) .subscribe(val => console.log(val));
這已經(jīng)好多了,mergeMap
將是這個問題的最佳解決方案。下面是完整的例子:
import { of, from } from "rxjs"; import { map, mergeMap, delay, mergeAll } from "rxjs/operators"; const getData = param => { return of(`檢索參數(shù): ${param}`).pipe(delay(1000)); }; // 使用 map from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log(data))); // 使用 map 和 mergeAll from([1, 2, 3, 4]) .pipe( map(param => getData(param)), mergeAll() ) .subscribe(val => console.log(val)); // 使用 mergeMap from([1, 2, 3, 4]) .pipe(mergeMap(param => getData(param))) .subscribe(val => console.log(val));
SwitchMap
具有類似的行為,它也將訂閱內(nèi)部可觀察對象。然而,switchMap
是switchAll
和map
的組合。SwitchAll
取消先前的訂閱并訂閱新訂閱。在上面的場景中,想要為“外部”可觀察對象數(shù)組中的每一項執(zhí)行API調(diào)用,但switchMap
并不能很好地工作,因為它將取消前3個訂閱,只處理最后一個訂閱。這意味著只會得到一個結果。完整的例子可以在這里看到:
import { of, from } from "rxjs"; import { map, delay, switchAll, switchMap } from "rxjs/operators"; const getData = param => { return of(`retrieved new data with param ${param}`).pipe(delay(1000)); }; // 使用 a regular map from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log(data))); // 使用 map and switchAll from([1, 2, 3, 4]) .pipe( map(param => getData(param)), switchAll() ) .subscribe(val => console.log(val)); // 使用 switchMap from([1, 2, 3, 4]) .pipe(switchMap(param => getData(param))) .subscribe(val => console.log(val));
雖然switchMap
不適用于當前的場景,但它適用于其他場景。例如,如果將篩選器列表組合到數(shù)據(jù)流中,并在更改篩選器時執(zhí)行API調(diào)用,那么它將派上用場。如果先前的篩選器更改仍在處理中,而新的更改已經(jīng)完成,那么它將取消先前的訂閱,并在最新的更改上啟動新的訂閱。這里可以看到一個例子:
import { of, from, BehaviorSubject } from "rxjs"; import { map, delay, switchAll, switchMap } from "rxjs/operators"; const filters = ["brand=porsche", "model=911", "horsepower=389", "color=red"]; const activeFilters = new BehaviorSubject(""); const getData = params => { return of(`接收參數(shù): ${params}`).pipe(delay(1000)); }; const applyFilters = () => { filters.forEach((filter, index) => { let newFilters = activeFilters.value; if (index === 0) { newFilters = `?${filter}`; } else { newFilters = `${newFilters}&${filter}`; } activeFilters.next(newFilters); }); }; // 使用 switchMap activeFilters.pipe(switchMap(param => getData(param))).subscribe(val => console.log(val)); applyFilters();
正如在控制臺中看到的,getData
只記錄一次所有參數(shù)。節(jié)省了3次API的調(diào)用。
最后一個例子是concatMap
。concatMap
訂閱了內(nèi)部可觀察對象。但與switchMap
不同的是,如果有一個新的觀察對象進來,它將取消當前觀察對象的訂閱,concatMap
在當前觀察對象完成之前不會訂閱下一個觀察對象。這樣做的好處是保持了可觀測對象發(fā)出信號的順序。為了演示這個:
import { of, from } from "rxjs"; import { map, delay, mergeMap, concatMap } from "rxjs/operators"; const getData = param => { const delayTime = Math.floor(Math.random() * 10000) + 1; return of(`接收參數(shù): ${param} and delay: ${delayTime}`).pipe(delay(delayTime)); }; // 使用map from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log("map:", data))); // 使用mergeMap from([1, 2, 3, 4]) .pipe(mergeMap(param => getData(param))) .subscribe(val => console.log("mergeMap:", val)); // 使用concatMap from([1, 2, 3, 4]) .pipe(concatMap(param => getData(param))) .subscribe(val => console.log("concatMap:", val));
getData
函數(shù)的隨機延遲在1到10000毫秒之間。通過瀏覽器日志,可以看到map
和mergeMap
操作符將記錄返回的任何值,而不遵循原始順序。concatMap
記錄的值與它們開始時的值相同。
將數(shù)據(jù)映射到所需的格式是一項常見的任務。RxJS
附帶了一些非常簡潔的操作符,可以很好的完成這項工作。
概括一下:map
用于將normal
值映射為所需的任何格式。返回值將再次包裝在一個可觀察對象中,因此可以在數(shù)據(jù)流中繼續(xù)使用它。當必須處理一個“內(nèi)部”觀察對象時,使用mergeMap
、switchMap
或concatMap
更容易。如果只是想將數(shù)據(jù)轉成Observable
對象,使用mergeMap
;如果需要丟棄舊的Observable
對象,保留最新的Observable
對象,使用switchMap
;如果需要將數(shù)據(jù)轉成Observable
對象,并且需要保持順序,則使用concatMap
。
以上是“Angular中RxJS怎么映射數(shù)據(jù)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
當前標題:Angular中RxJS怎么映射數(shù)據(jù)
文章鏈接:http://chinadenli.net/article14/iegide.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、品牌網(wǎng)站建設、微信公眾號、虛擬主機、云服務器、定制網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)