通过承诺过滤数组

Filter array observable by promise

我有

如何通过承诺过滤这个数组?

我尝试了很多东西,最接近的是

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));

JB Nizet nice solution, but it would be better to use concatMap, if item order matters. Here 解释了 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 两种解决方案的工作示例。