溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Angular中RxJS怎么映射數據

發布時間:2021-07-06 13:54:46 來源:億速云 閱讀:203 作者:小新 欄目:web開發

小編給大家分享一下Angular中RxJS怎么映射數據,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

Map 數據是程序開發時的一種常見操作。當在代碼中使用RxJS來生成數據流時,很可能最終需要一種方法來將數據映射成需要的任何格式。RxJS提供了常規的 map 函數,還有 mergeMap、switchMapconcatMap這樣的函數,它們的處理方式略有不同。

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次。

  • 第一次修改數據時,得到了一個由brandmodel字符串連接起來的數組。

  • 第二次修改數據時,得到了一個只有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本質上是mergeAllmap的組合。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具有類似的行為,它也將訂閱內部可觀察對象。然而,switchMapswitchAllmap的組合。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毫秒之間。通過瀏覽器日志,可以看到mapmergeMap操作符將記錄返回的任何值,而不遵循原始順序。concatMap記錄的值與它們開始時的值相同。

總結

將數據映射到所需的格式是一項常見的任務。RxJS附帶了一些非常簡潔的操作符,可以很好的完成這項工作。

概括一下:map用于將normal值映射為所需的任何格式。返回值將再次包裝在一個可觀察對象中,因此可以在數據流中繼續使用它。當必須處理一個“內部”觀察對象時,使用mergeMap、switchMapconcatMap更容易。如果只是想將數據轉成Observable對象,使用mergeMap;如果需要丟棄舊的Observable對象,保留最新的Observable對象,使用switchMap;如果需要將數據轉成Observable對象,并且需要保持順序,則使用concatMap。

以上是“Angular中RxJS怎么映射數據”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女