诺言可观察的过滤器阵列

时间:2019-08-03 07:45:14

标签: typescript filter rxjs mergemap

我有

  • 对象数组
  • 函数permission(obj): Promise<boolean>

如何根据承诺过滤此数组?

我尝试了很多事情,而最接近的是

of(arr).pipe(
  switchMap(items =>
    from(items)
     .pipe(
       mergeMap(item =>
         fromPromise(permission(item)).pipe(
           map(shown => ({show, item})),
           filter(data => data.shown),
           map(data => data.item)
         )
       ))
     ));

但这似乎不必要地复杂。

我曾经希望我可以像of(arr).pipe(filterByPromise(permission))这样更简单,但是似乎无法弄清楚该怎么做。

我进行了一次Stackblitz https://stackblitz.com/edit/rxjs-g1u8yk

StackBlitz代码

import { of } from 'rxjs'; 
import { map, filter } from 'rxjs/operators';

// Mocked 3rd party function
function visible(obj): Promise<boolean> {
  return new Promise(resolve => {
    const shouldShow = obj.shouldShow < 30;
    resolve(shouldShow);
  });
}

const arr = [{
  shouldShow: 39,
  data1: 'abc',
  data2: 'bcd'
}, {
  shouldShow: 22,
  data1: 'cde',
  data2: 'def'
}];

of(arr).pipe(
  filter(obj => visible(obj))
).subscribe(result => console.log(result));

1 个答案:

答案 0 :(得分:1)

JB Nizet suggested是一个很好的解决方案,但是如果项目顺序很重要,最好使用concatMapHere解释了concatMapmergeMap之间的区别。

from(arr).pipe(
  concatMap(element => from(visible(element)).pipe(
    filter(show => show),
    map(() => element)
  ))
).subscribe(console.log);

另一种方法是像这样转换和zip数组。但是我认为解决方案更为优雅。

zip(...arr.map(obj => from(visible(obj)))).pipe(
  map(visible => arr.filter((item, i) => visible[i]))
).subscribe(console.log);

Here is两种解决方案的工作示例。