Может ли это быть реорганизовано в более сложный стиль, который можно увидеть в примерах? - PullRequest
1 голос
/ 08 мая 2019

Я довольно новичок в rxjs, и этот пример, который я привел, не выглядит таким элегантным.По сути, как я могу объединить 3 совершенно разные наблюдаемые в одну?Можете ли вы сделать это в стиле функций высшего порядка, как во многих онлайн-примерах?

createFilteredDataObservable(initialData: Observable<Data[]>,
                             valueSource: Observable<any>, 
                             clickSource: Subject<boolean>): Observable<Data[]> {
    let data: Data[] = [];
    let text = '';

    initialData.subscribe(value => {
      data= value;
    });

    function format(x: string): string {
      return x.toLowerCase().trim();
    }

    function filter() {
      if (text === '') {
        return data;
      }

      const result = data.filter(d=> {
        const name = format(d.DisplayName);
        return name === text || name.includes(text);
      });

      return result;
    }

    return new Observable<Data[]>((observer) => {

      clickSource.subscribe(_ => {
        const result = filter();
        observer.next(result);
      });

      valueSource.subscribe((v: string|Data) => {
        if (typeof v !== 'string') {
          return;
        }
        text = format(v);
        const result = filter();
        observer.next(result);
      });

    });
}

1 Ответ

1 голос
/ 08 мая 2019

Зависит от того, что вы пытаетесь сделать, но примерно это должно выглядеть примерно так ...

const filtered = data.pipe(switchMap(data => {
  return value.pipe(startWith(''), combineLatest(clicks.pipe(startWith(null))), map(([value, _]) => {
    return data.filter(item => item.includes(value));
  }));
}));

Вот Гист, с которым вы можете играть: https://gist.github.com/westonpace/4f7811b6735c94e97928be1bb6a377ce

Iисключил format и упростил filter для краткости, но этого можно добиться, бросив map на value между startWith и combineLatest.Это будет вести себя не так, как ваш код, с некоторыми незначительными способами, которые вы можете настроить, если хотите.

В вашем примере, если initialData холодный и требует времени для запуска и clickSource и valueSourceраньше, чем вы могли бы получить пустой массив.В моем примере вы не получите никаких результатов, пока initialData не сработает хотя бы один раз.Вы можете использовать startWith на data до switchMap, если вы хотите такое поведение.

Кроме того, в вашем примере, если initalData сработал во второй раз, ничего не произойдет (наблюдаемая будет продолжать фильтровать старое исходное значение), где в этом примере, если initialData сработает снова, он переключитсяперейти к фильтрации нового массива, но, вероятно, потеряет значение из valueSource.

В вашем примере вы не получите никаких результатов для начала, и тогда будет получен первый результат, если clickSource или valueSourceПожар.Я не мог придумать способ воспроизвести это точно на макушке.Мой код сработает сразу же, как только data сработает.Если вы отключите startWith на clicks, то оно сработает только при срабатывании clickSource.Если вы выключите startWith на value, он сработает только тогда, когда valueSource сработает хотя бы один раз.Если вам действительно нужно это поведение, вы можете начать вместо data.filter с merge(clicks, value).pipe(switchMap(_ => data.filter...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...