首页前端开发JavaScript浅谈Angular中RxJS如何映射数据操作

浅谈Angular中RxJS如何映射数据操作

时间2024-01-30 00:12:03发布访客分类JavaScript浏览326
导读:收集整理的这篇文章主要介绍了浅谈Angular中RxJS如何映射数据操作,觉得挺不错的,现在分享给大家,也给大家做个参考。Map 数据是程序开发时的一种常见操作。当在代码中使用RxJS来生成数据流时,很可能最终需要一种方法来将数据映射成需要...
收集整理的这篇文章主要介绍了浅谈Angular中RxJS如何映射数据操作,觉得挺不错的,现在分享给大家,也给大家做个参考。

Map 数据是程序开发时的一种常见操作。当在代码中使用RxJS来生成数据流时,很可能最终需要一种方法来将数据映射成需要的任何格式。RxJS提供了常规的 map 函数,还有 mergeMapswITchMapconcatMap这样的函数,它们的处理方式略有不同。【相关教程推荐:《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次。

  • 第一次修改数据时,得到了一个由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));
}
    ;
    // 使用 mapfrom([1, 2, 3, 4])    .pipe(map(param =>
     getData(param)))    .subscribe(val =>
     val.subscribe(data =>
     console.log(data)));
    // 使用 map 和 mergeAllfrom([1, 2, 3, 4])    .pipe(        map(param =>
     getData(param)),        mergeAll()    )    .subscribe(val =>
     console.log(val));
    // 使用 mergeMapfrom([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 mapfrom([1, 2, 3, 4])    .pipe(map(param =>
     getData(param)))    .subscribe(val =>
     val.subscribe(data =>
     console.log(data)));
    // 使用 map and switchAllfrom([1, 2, 3, 4])    .pipe(        map(param =>
     getData(param)),        switchAll()    )    .subscribe(val =>
     console.log(val));
    // 使用 switchMapfrom([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);
    }
    );
}
    ;
    // 使用 switchMapactiveFilters.pipe(switchMap(param =>
     getData(param))).subscribe(val =>
     console.log(val));
    applyFilters();
    

正如在控制台中看到的,getData只记录一次所有参数。节省了3次API的调用。

ConcatMap

最后一个例子是concatMapconcatMap订阅了内部可观察对象。但与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));
}
    ;
    // 使用Mapfrom([1, 2, 3, 4])    .pipe(map(param =>
     getData(param)))    .subscribe(val =>
     val.subscribe(data =>
     console.log("map:", data)));
    // 使用mergeMapfrom([1, 2, 3, 4])    .pipe(mergeMap(param =>
     getData(param)))    .subscribe(val =>
     console.log("mergeMap:", val));
    // 使用concatMapfrom([1, 2, 3, 4])    .pipe(concatMap(param =>
     getData(param)))    .subscribe(val =>
     console.log("concatMap:", val));
    

getData函数的随机延迟在1到10000毫秒之间。通过浏览器日志,可以看到mapmergeMap操作符将记录返回的任何值,而不遵循原始顺序。concatMap记录的值与它们开始时的值相同。

总结

将数据映射到所需的格式是一项常见的任务。RxJS附带了一些非常简洁的操作符,可以很好的完成这项工作。

概括一下:map用于将normal值映射为所需的任何格式。返回值将再次包装在一个可观察对象中,因此可以在数据流中继续使用它。当必须处理一个“内部”观察对象时,使用mergeMapswitchMapconcatMap更容易。如果只是想将数据转成Observable对象,使用mergeMap;如果需要丢弃旧的Observable对象,保留最新的Observable对象,使用switchMap;如果需要将数据转成Observable对象,并且需要保持顺序,则使用concatMap

更多编程相关知识,请访问:编程视频!!

以上就是浅谈Angular中RxJS如何映射数据操作的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

AngularRxJS

若转载请注明出处: 浅谈Angular中RxJS如何映射数据操作
本文地址: https://pptw.com/jishu/591784.html
javascript如何隐藏下拉菜单 JavaScript自定义函数的写法是什么

游客 回复需填写必要信息