Селектор NGRX запрашивает данные до того, как они появятся в магазине

Когда пользователь выбирает элемент на экране, запускается действие, которое запрашивает данные из API и загружает эти данные в хранилище для выбранного элемента.

Селектор используется для захвата определенных частей возвращенных данных для создания графика.

Селектор возвращает значение undefined, потому что в магазине еще нет этих данных.

Мне либо нужно, чтобы хранилище / действие / отправка сигнализировали вызову селектора, что он готов, ИЛИ разрешить селектору продолжать запрашивать, пока он не получит данные, которые он ищет:

this.setItemDispatch(this.datetime, this.selectedItem, this.direction);

this.store.select(selectFlyoutTimelineBar(this.selectedItem, this.direction, 'Graph Title')).subscribe(x => {
  console.log('data returned:', x);
});

Отправка:

this.store.dispatch(
          new LoadStationArriveTimelineDataAction({
            station: selectedItem,
            start: { startDate: currentDate },
            query: this.codes,
            lineQuery: this.lineCode
          })
        );

person dcp3450    schedule 31.08.2018    source источник


Ответы (5)


Вы можете использовать операцию RxJS filter.

this.store.pipe(
  select(selectFlyoutTimelineBar(this.selectedItem, this.direction, 'Graph Title')),
  filter(result => Boolean(result))
)

Мне либо нужно, чтобы хранилище / действие / отправка сигнализировали вызову селектора, что он готов, ИЛИ разрешить селектору продолжать запрашивать, пока он не получит данные, которые он ищет:

Селектор - это наблюдаемый объект RxJS, каждый раз, когда его данные изменяются, он будет выдавать новое значение. Это означает, что вам не нужно уведомлять селектор об обновлении.

person timdeschryver    schedule 31.08.2018

Подобно тому, как @timdeschryver сказал: «Селектор - это наблюдаемый RxJS, каждый раз, когда его данные изменяются, он будет выдавать новое значение. Это означает, что вам не нужно уведомлять селектор об обновлении». мой селектор не собирал обновление в магазине, потому что ничего не говорило моему селектору, что магазин обновлен. Мой селектор фильтрует данные магазина, а не отслеживает прямое изменение элементов в магазине.

У меня есть другой селектор, который ищет изменения по конкретным элементам. Я подписался на этот селектор и вложил туда свой selectFlyoutTimelineBar селектор, который в основном говорит: «Когда выбранный вами элемент обновлен, возьмите graphdata, потому что он доступен сейчас»

person dcp3450    schedule 31.08.2018

Если данные недоступны, селектор вернет значение null. Затем в своей подпрограмме вы можете отфильтровать null следующим образом:

this.store.select(selectFlyoutTimelineBar(this.selectedItem, this.direction, 'Graph Title'))
  .pipe(
    filter(x => x != null)
  )
  .subscribe(x => {
    console.log('data returned:', x);
  });

Это приведет к выполнению подпрограммы только в том случае, если селектор не вернет null. PS ваш оператор выбора должен быть внутри трубы ()

person danday74    schedule 31.08.2018
comment
Это работает, но я считаю skipWhile (x = ›x === null) немного более читаемым - person Alan Gee; 12.06.2020

Кажется, вам нужно определить initialState и сделать его значением по умолчанию для вашего редуктора.

export const initialState: State = { prop1: null, prop2: null }

Затем в вашем редукторе

export class reducer(state: State = initialState, action: YourAction)

Он обязательно исключит undefined и аккуратно обработает хранилище до того, как значение станет доступным.

person Xinan    schedule 01.09.2018

Похоже, вы ищете оператор combineLatest, который излучает, когда все исходные Observable излучают хотя бы один элемент, а затем при каждом излучении из любого источника Observable. Но сложно сказать, что именно вы хотите делать:

const selector$ = action$.pipe(ofType(...))

combineLatest(this.store.select(...), selector$)
  .pipe(
    map([data, selector] => /* filter data or whatever */)
  )
  .subscribe(...)

Возможно, вам даже не нужно использовать map().

Если селектором является другой Observable и вам нужно его значение перед отправкой this.store.select(...) запроса, вы можете связать его с concatMap, например:

selector$
  .pipe(
    concatMap(selector => this.store.select(...selector...))
  )
  .subscribe(...)
person martin    schedule 31.08.2018