Angular中RxJS怎么映射數(shù)據(jù)

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

創(chuàng)新互聯(lián)主要從事網(wǎng)站設(shè)計(jì)制作、做網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)銅山,10年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):18980820575

Map 數(shù)據(jù)是程序開(kāi)發(fā)時(shí)的一種常見(jiàn)操作。當(dāng)在代碼中使用RxJS來(lái)生成數(shù)據(jù)流時(shí),很可能最終需要一種方法來(lái)將數(shù)據(jù)映射成需要的任何格式。RxJS提供了常規(guī)的 map 函數(shù),還有 mergeMap、switchMapconcatMap這樣的函數(shù),它們的處理方式略有不同。

map

map操作符是最常見(jiàn)的。對(duì)于Observable發(fā)出的每個(gè)值,都可以應(yīng)用一個(gè)函數(shù)來(lái)修改數(shù)據(jù)。返回值將在后臺(tái)被重新釋放為Observable,這樣就可以在流中繼續(xù)使用它。它的工作原理與在數(shù)組中使用它的方法非常相似。

不同之處在于,數(shù)組將始終只是數(shù)組,而在映射時(shí),將獲得數(shù)組中當(dāng)前的索引值。對(duì)于observable,數(shù)據(jù)的類型可以是各種類型。這意味著可能需要在 Observable map 函數(shù)中做一些額外的操作來(lái)獲得想要的結(jié)果??聪旅娴睦樱?

import { of } from "rxjs";
import { map } from "rxjs/operators";

// 創(chuàng)建數(shù)據(jù)
const data = of([
    {
        brand: "保時(shí)捷",
        model: "911"
    },
    {
        brand: "保時(shí)捷",
        model: "macan"
    },
    {
        brand: "法拉利",
        model: "458"
    },
    {
        brand: "蘭博基尼",
        model: "urus"
    }
]);

// 按照brand model的格式輸出,結(jié)果:["保時(shí)捷 911", "保時(shí)捷 macan", "法拉利 458", "蘭博基尼 urus"]
data.pipe(map(cars => cars.map(car => `${car.brand} ${car.model}`))).subscribe(cars => console.log(cars));

// 過(guò)濾數(shù)據(jù),只保留brand為porsche的數(shù)據(jù),結(jié)果:[{"brand":"保時(shí)捷","model":"911"},{"brand":"保時(shí)捷","model":"macan"}]
data.pipe(map(cars => cars.filter(car => car.brand === "保時(shí)捷"))).subscribe(cars => console.log(cars));

首先用一系列汽車創(chuàng)建了可觀察對(duì)象。然后訂閱這個(gè)可觀測(cè)值2次。

  • 第一次修改數(shù)據(jù)時(shí),得到了一個(gè)由brandmodel字符串連接起來(lái)的數(shù)組。

  • 第二次修改數(shù)據(jù)時(shí),得到了一個(gè)只有brand保時(shí)捷的數(shù)組。

在這兩個(gè)例子中,使用Observable map操作符來(lái)修改由Observable發(fā)出的數(shù)據(jù)。返回修改的結(jié)果,然后map操作符將結(jié)果封裝到一個(gè)可觀察對(duì)象中,以便后面可以subscribe

MergeMap

現(xiàn)在假設(shè)有這樣一個(gè)場(chǎng)景,有一個(gè)可觀察到的對(duì)象,它發(fā)出一個(gè)數(shù)組,對(duì)于數(shù)組中的每一項(xiàng),都需要從服務(wù)器獲取數(shù)據(jù)。

可以通過(guò)訂閱數(shù)組來(lái)做到這一點(diǎn),然后設(shè)置一個(gè)映射來(lái)調(diào)用一個(gè)處理API調(diào)用的函數(shù),訂閱其結(jié)果。如下:

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ù)的值。在這種情況下,這是可觀測(cè)的。但這產(chǎn)生了一個(gè)問(wèn)題:因?yàn)楝F(xiàn)在要處理一個(gè)額外的可觀測(cè)值。

為了進(jìn)一步闡明這一點(diǎn):from([1,2,3,4])作為“外部”可觀察對(duì)象,getData()的結(jié)果作為“內(nèi)部”可觀察對(duì)象。從理論上講,必須同時(shí)接受外部和內(nèi)部的可觀測(cè)數(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兩次的理想情況相去甚遠(yuǎn)。這就是mergeMap發(fā)揮作用的地方。MergeMap本質(zhì)上是mergeAllmap的組合。MergeAll負(fù)責(zé)訂閱“內(nèi)部”可觀察對(duì)象,當(dāng)MergeAll將“內(nèi)部”可觀察對(duì)象的值合并為“外部”可觀察對(duì)象時(shí),不再需要訂閱兩次。如下:

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將是這個(gè)問(wèn)題的最佳解決方案。下面是完整的例子:

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

SwitchMap具有類似的行為,它也將訂閱內(nèi)部可觀察對(duì)象。然而,switchMapswitchAllmap的組合。SwitchAll取消先前的訂閱并訂閱新訂閱。在上面的場(chǎng)景中,想要為“外部”可觀察對(duì)象數(shù)組中的每一項(xiàng)執(zhí)行API調(diào)用,但switchMap并不能很好地工作,因?yàn)樗鼘⑷∠?個(gè)訂閱,只處理最后一個(gè)訂閱。這意味著只會(huì)得到一個(gè)結(jié)果。完整的例子可以在這里看到:

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不適用于當(dāng)前的場(chǎng)景,但它適用于其他場(chǎng)景。例如,如果將篩選器列表組合到數(shù)據(jù)流中,并在更改篩選器時(shí)執(zhí)行API調(diào)用,那么它將派上用場(chǎng)。如果先前的篩選器更改仍在處理中,而新的更改已經(jīng)完成,那么它將取消先前的訂閱,并在最新的更改上啟動(dòng)新的訂閱。這里可以看到一個(gè)例子:

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();

正如在控制臺(tái)中看到的,getData只記錄一次所有參數(shù)。節(jié)省了3次API的調(diào)用。

ConcatMap

最后一個(gè)例子是concatMap。concatMap訂閱了內(nèi)部可觀察對(duì)象。但與switchMap不同的是,如果有一個(gè)新的觀察對(duì)象進(jìn)來(lái),它將取消當(dāng)前觀察對(duì)象的訂閱,concatMap在當(dāng)前觀察對(duì)象完成之前不會(huì)訂閱下一個(gè)觀察對(duì)象。這樣做的好處是保持了可觀測(cè)對(duì)象發(fā)出信號(hào)的順序。為了演示這個(gè):

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ù)的隨機(jī)延遲在1到10000毫秒之間。通過(guò)瀏覽器日志,可以看到mapmergeMap操作符將記錄返回的任何值,而不遵循原始順序。concatMap記錄的值與它們開(kāi)始時(shí)的值相同。

總結(jié)

將數(shù)據(jù)映射到所需的格式是一項(xiàng)常見(jiàn)的任務(wù)。RxJS附帶了一些非常簡(jiǎn)潔的操作符,可以很好的完成這項(xiàng)工作。

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

以上是“Angular中RxJS怎么映射數(shù)據(jù)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

當(dāng)前標(biāo)題:Angular中RxJS怎么映射數(shù)據(jù)
文章鏈接:http://muchs.cn/article14/iegide.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、品牌網(wǎng)站建設(shè)、微信公眾號(hào)虛擬主機(jī)、云服務(wù)器定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁(yè)設(shè)計(jì)公司