1

我有

  • 对象数组
  • 一个函数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));
4

1 回答 1

1

JB Nizet提出了很好的解决方案,但concatMap如果项目顺序很重要,最好使用 。这里concatMap解释了和之间的区别mergeMap

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

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

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

这是两种解决方案的工作示例。

于 2019-08-03T09:32:27.047 回答