【问题标题】:convert rjxs map and flatten/reduce to flatMap将 rjxs map 和 flatten/reduce 转换为 flatMap
【发布时间】:2018-08-17 22:03:34
【问题描述】:

我相信可以使用 flatMap 重构以下代码,但我似乎无法让它按预期工作。

我理解 flatMap 本质上是映射然后变平,这对我来说是完美的,因为我正在使用 forkJoin,所以从 getAutocompleteSuggestions() 获取一系列响应。

我想要订阅时的单个结果数组(这是下面的代码产生的结果),但是将顶级地图更改为 flatMap 会将多个单个对象发送到订阅。如何用 flatMap() 更好地编写这段代码?

   const $resultsObservable: Observable<any> = Observable.of(query)
          .switchMap(q => this.getAutocompleteSuggestions(q))
          //tried changing the below to flatMap()
          .map(res => { 
            return res.map(resp => {
              const content = resp.content;
              content.map(result => this.someMethod(result));
              return content;
            })
            .reduce((flatArr, subArray) => flatArr.concat(subArray), []);
          });



  getAutocompleteSuggestions(query: string): Observable<any> {
    const subs$ = [];
    //... add some observables to $subs
    return Observable.forkJoin(...subs$);
  }

【问题讨论】:

  • content.map(…) 行有错误或不清楚。由于您不使用它的结果,someMethod 被执行,但不是可观察链中返回的结果。如果这是有意的,您应该在可观察级别上以副作用 (do) 运行它,并在数组级别上使用 forEachmap(在两个级别上)用于映射数据,而不是执行副作用。
  • resp.content 是一个数组,所以我对其进行转换然后返回它,基本上丢弃了其他所有内容,并转换了我需要的数据
  • map 不会就地修改数组。
  • 可以,但是传入的变量(结果)是通过引用传递的,在(通过引用传递的)数组中修改和保持修改的对象
  • 那么你应该使用forEachmap 不是为了副作用。代码可能有效,只是设计糟糕,违反了最小意外原则。

标签: javascript angular typescript rxjs rxjs5


【解决方案1】:

看起来 RxJS flatMap 和数组原型方法 flatMap 之间可能有些混淆。请注意,RxJS flatMap 的目的不是将作为流的主题的数组展平,而是将 Obervable 的流展平为单个 observable。请参阅此 SO 帖子:

Why do we need to use flatMap?

... 基本上,如果 Observable 表示一个可观察对象,它推送类型为 T 的值,那么 flatMap 将一个类型为 T' -> Observable 的函数作为其参数,并返回 Observable。 map 接受一个 T' -> T 类型的函数并返回 Observable。

如果您希望代码更简洁,可以使用myArray.flatMap 方法。这是使用 Array flatMap 方法对您的问题的潜在答案:

const $resultsObservable: Observable<any> = Observable.of(query)
  .switchMap(q => this.getAutocompleteSuggestions(q))
  // Flatmap on the array here because response is an array of arrays.
  // The RxJS flatMap does not deal with flattening arrays
  .map(res => res.flatMap(resp => {
    const content = resp.content;
    content.map(result => this.someMethod(result));
    return content;
  }));

getAutocompleteSuggestions(query: string): Observable < any > {
  const subs$ = [];
  //... add some observables to $subs
  return Observable.forkJoin(...subs$);
}

【讨论】:

  • 在这一行:.map(res => res.flatMap(resp => { res 是一个数组,所以我得到一个错误,“res.flatMap is not a function”
  • 抱歉,flatMap 方法不是 javascript 规范的一部分 - 它只是被提出并且是 not supported by any browsers yet。看起来您可能必须使用 map 和您自己的 flatten 方法的组合。或者您可以尝试使用像 lodashunderscore 这样的库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多