Map
資料是程式開發時的常見操作。當程式碼中使用RxJS
來產生資料流時,很可能最終需要一種方法來將資料對應成需要的任何格式。 RxJS
提供了常規的map
函數,還有mergeMap
、switchMap
和concatMap
這樣的函數,它們的處理方式略有不同。 【相關教學推薦:《angular教學》】
map
map
運算子是最常見的。對於Observable
發出的每個值,都可以套用一個函數來修改資料。傳回值將在背景被重新釋放為Observable
,這樣就可以在流中繼續使用它。它的工作原理與在數組中使用它的方法非常相似。
不同之處在於,數組將始終只是數組,而在映射時,將獲得數組中當前的索引值。對於observable
,資料的型別可以是各種型別。這意味著可能需要在 Observable map
函數中做一些額外的操作來獲得想要的結果。看下面的範例::
import { of } from "rxjs"; import { map } from "rxjs/operators"; // 创建数据 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)); // 过滤数据,只保留brand为porsche的数据,结果:[{"brand":"保时捷","model":"911"},{"brand":"保时捷","model":"macan"}] data.pipe(map(cars => cars.filter(car => car.brand === "保时捷"))).subscribe(cars => console.log(cars));
首先用一系列汽車建立了可觀察物件。然後訂閱這個可觀測值2次。
第一次修改資料時,得到了一個由
brand
和model
字串連接起來的陣列。第二次修改資料時,得到了一個只有
brand
為保時捷
的陣列。
在這兩個範例中,使用Observable
map運算子來修改由Observable
所發出的資料。傳回修改的結果,然後map
運算子將結果封裝到一個可觀察物件中,以便後面可以subscribe
。
MergeMap
現在假設有這樣一個場景,有一個可觀察到的對象,它發出一個數組,對於數組中的每一項,都需要從伺服器獲取數據。
可以透過訂閱陣列來做到這一點,然後設定一個映射來呼叫一個處理API呼叫的函數,訂閱其結果。如下:
import { of, from } from "rxjs"; import { map, delay } from "rxjs/operators"; const getData = param => { return of(`检索参数: ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => console.log(val));
map
函數傳回getData
函數的值。在這種情況下,這是可觀測的。但這產生了一個問題:因為現在要處理一個額外的可觀測值。
為了進一步闡明這一點:from([1,2,3,4])
作為「外部」可觀察對象,getData()
的結果作為“內部”可觀察對象。從理論上講,必須同時接受外部和內部的可觀測資料。可以是這樣的:
import { of, from } from "rxjs"; import { map, delay } from "rxjs/operators"; const getData = param => { return of(`检索参数: ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe(map(param => getData(param))) .subscribe(val => val.subscribe(data => console.log(data)));
可以想像,這與必須調用Subscribe
兩次的理想情況相去甚遠。這就是mergeMap
發揮作用的地方。 MergeMap
本質上是mergeAll
和map
的組合。 MergeAll
負責訂閱「內部」可觀察對象,當MergeAll
將「內部」可觀察對象的值合併為「外部」可觀察對象時,就不再需要訂閱兩次。如下:
import { of, from } from "rxjs"; import { map, delay, mergeAll } from "rxjs/operators"; const getData = param => { return of(`检索参数: ${param}`).pipe(delay(1000)); }; from([1, 2, 3, 4]) .pipe( map(param => getData(param)), mergeAll() ) .subscribe(val => console.log(val));
這已經好多了,mergeMap
將是這個問題的最佳解決方案。以下是完整的範例:
import { of, from } from "rxjs"; import { map, mergeMap, delay, mergeAll } from "rxjs/operators"; const getData = param => { return of(`检索参数: ${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
#SwitchMap
有類似的行為,它也會訂閱內部可觀察物件。然而,switchMap
是switchAll
和map
的組合。 SwitchAll
取消先前的訂閱並訂閱新訂閱。在上面的場景中,想要為「外部」可觀察物件數組中的每一項執行API調用,但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
不適用於當前的場景,但它適用於其他場景。例如,如果將篩選器清單組合到資料流中,並在更改篩選器時執行API調用,那麼它將派上用場。如果先前的篩選器變更仍在處理中,而新的變更已經完成,那麼它將取消先前的訂閱,並在最新的變更上啟動新的訂閱。這裡可以看到一個例子:
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(`接收参数: ${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
只記錄一次所有參數。節省了3次API的呼叫。
ConcatMap
最後一個例子是concatMap
。 concatMap
訂閱了內部可觀察物件。但與switchMap
不同的是,如果有一個新的觀察對象進來,它將取消當前觀察對象的訂閱,concatMap
在當前觀察對象完成之前不會訂閱下一個觀察對象。這樣做的好處是保持了可觀測物件發出訊號的順序。為了示範這個:
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(`接收参数: ${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
函数的随机延迟在1到10000毫秒之间。通过浏览器日志,可以看到map
和mergeMap
操作符将记录返回的任何值,而不遵循原始顺序。concatMap
记录的值与它们开始时的值相同。
总结
将数据映射到所需的格式是一项常见的任务。RxJS
附带了一些非常简洁的操作符,可以很好的完成这项工作。
概括一下:map
用于将normal
值映射为所需的任何格式。返回值将再次包装在一个可观察对象中,因此可以在数据流中继续使用它。当必须处理一个“内部”观察对象时,使用mergeMap
、switchMap
或concatMap
更容易。如果只是想将数据转成Observable
对象,使用mergeMap
;如果需要丢弃旧的Observable
对象,保留最新的Observable
对象,使用switchMap
;如果需要将数据转成Observable
对象,并且需要保持顺序,则使用concatMap
。
更多编程相关知识,请访问:编程视频!!
以上是淺談Angular中RxJS如何映射資料操作的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本篇文章继续Angular的学习,带大家了解一下Angular中的元数据和装饰器,简单了解一下他们的用法,希望对大家有所帮助!

本篇文章带大家深入了解一下angular的状态管理器NgRx,介绍一下NgRx的使用方法,希望对大家有所帮助!

angular中怎么使用monaco-editor?下面本篇文章记录下最近的一次业务中用到的 monaco-editor 在 angular 中的使用,希望对大家有所帮助!

本篇文章给大家分享一个Angular实战,了解一下angualr 结合 ng-zorro 如何快速开发一个后台系统,希望对大家有所帮助!

Angular项目过大,怎么合理拆分它?下面本篇文章给大家介绍一下合理拆分Angular项目的方法,希望对大家有所帮助!

怎么自定义angular-datetime-picker格式?下面本篇文章聊聊自定义格式的方法,希望对大家有所帮助!

本篇文章带大家了解一下Angular中的独立组件,看看怎么在Angular中创建一个独立组件,怎么在独立组件中导入已有的模块,希望对大家有所帮助!

Angular Route中怎么提前获取数据?下面本篇文章给大家介绍一下从 Angular Route 中提前获取数据的方法,希望对大家有所帮助!


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver CS6
視覺化網頁開發工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

記事本++7.3.1
好用且免費的程式碼編輯器

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中