【问题标题】:Mapping values from combineLatest to Array将值从 combineLatest 映射到 Array
【发布时间】:2018-07-21 07:54:03
【问题描述】:

有这个:

 Observable.combineLatest(localArray.map((i) => {
  return <Observable that returns $value> }))
  .map((statuses) => {
    return statuses.filter((status) => {
      return status.$value === CONDITION
    });
  }).subscribe((eligible: any[]) => {
...

是否可以将订阅结果映射回localArray?我想知道哪个eligible项目属于哪个localArray条目...

感谢您的帮助。

我在某处读到该订单使用combineLatest 保留。但是,使用forEach 直接映射到索引将不起作用,因为如果满足条件,eligible 结果可能返回与localArray 不同的长度。

我总是可以删除 .map() 并在 subscribe 块中进行过滤,这将使我能够循环 localArray 并直接使用 eligible 数据更新:localArray.forEach((ai, i) =&gt; { ai.eligible = eligible[i] }) for例子...

【问题讨论】:

  • 您好!首先,为什么要使用 combineLatest 和映射数组的结果? Observable.from(localArray) 不会做你需要的吗?或者对数组中的每个元素都有一个请求?
  • 嗨@BorisLobanov!是的,对数组中的每个元素都有一个请求。

标签: javascript typescript ecmascript-6 rxjs


【解决方案1】:

根据您提供的少量信息确实很难判断这是否是一个好主意,但在我看来肯定不是这样。我之所以这么说是因为映射回localArray 会在您的数据流中创建一个隐式循环。也许这正是您所需要的,所以这取决于您。

在这种情况下,您可以做的就是发出 index(或其他标识符),帮助您从 combineLatest 映射回 localArray

类似的东西。

Observable.combineLatest(localArray.map((i) => {
  return <Observable that returns $value> }))
  .map((statuses) => {
    return [i, statuses.filter((status) => {
      return status.$value === CONDITION
    })];
  }).subscribe((eligible: [number, any[]]) => {
    // eligible now is a tuple type where the left element is the index of the localArray
  });

【讨论】:

  • i 在第二个 map 中未定义
  • 因此,从您可以访问i 的任何地方传递它,或者传递任何其他有助于您参考要更新的内容的下游内容。这才是重点。你的代码一开始就被破坏了,所以不要把我的例子从字面上看。
【解决方案2】:

一、代码:

Observable
    // Turn an array, promise, or iterable into an observable.
    .from(localArray)
    // Map values to inner observable, subscribe and emit in order.
    .concatMap((arrayElement: any) => {
        // Returning an observable that returns a value
        return Observable.of(arrayElement);
    })
    // Emit only values that meet the provided condition.
    .filter((value: any) => {
        return value === 'Some condition';
    })
    // Reduces the values from source observable to a single value that's emitted when the source completes.
    // If you need the current accumulated value on each emission, try scan - https://www.learnrxjs.io/operators/transformation/scan.html
    // The second argument here is the seed, the initial value provided the first time reduce is called. (In this case, an empty array)
    .reduce((filteredValue: any, accumulatedFilteredValues: any[]) =>{
        accumulatedFilteredValues.push(filteredValue);
        return accumulatedFilteredValues;
    }, [])
    .subscribe((filteredValueArray: any[]) => {
        // Do something with the array of ordered, filtered values
    });

首先,我使用from 创建了一个可观察对象来发射localArray 中的每个arrayElement。

当每个arrayElement 发出时,我将arrayElement 映射到将返回一些value 的Observable(在这种情况下我只返回arrayElement)。我正在使用concatMap,因为它会订阅内部可观察对象并在完成后发出它们的值,按照发出的顺序

我使用filter 只发出满足条件的value。过滤器采用返回truefalse 的函数。如果返回true,则会发出value

最后,我使用reduce 收集filteredValue 并将其添加到accumulatedFilteredValues 的数组中。 Reduce 接受一个函数作为它的第一个参数,一个可选的种子作为它的第二个参数。

传递给reduce的函数接收最近的发射(filteredValue)作为其第一个参数,并接收一个累积值作为第二个参数(空数组[])

将这些运算符应用于发出的值后,传递给 subscribe 的函数会接收一个数组,其中包含来自localArray 的过滤后的有序项。

learn-rxjs 是一个优秀的 RxJS 资源,包含各种运算符的示例和描述。

如果您使用的是 RxJS >= 5.5,请考虑改用 pipeable operators。在这种情况下,代码看起来会更接近于这个:

from(localArray).pipe(
        concatMap((arrayElement: any) => {
            return Observable.of(arrayElement);
        }),
        filter(value => {
            return value === 'Some condition';
        }),
        reduce((filteredValue: any, accumulatedFilteredValues: any[]) => {
            accumulatedFilteredValues.push(filteredValue);
            return accumulatedFilteredValues;
        }, [])
    )
    .subscribe((filteredValueArray: any[]) => {
        // Do something with the array of ordered, filtered values
    });

【讨论】:

    猜你喜欢
    • 2022-01-17
    • 2017-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 2019-12-29
    • 1970-01-01
    相关资源
    最近更新 更多