Как создать эффект NGRX, который принимает запись из состояния каждые 5 секунд, если доступно? - PullRequest
1 голос
/ 02 апреля 2020

Я хочу создать очередь сообщений с использованием NGRX, каждое сообщение, добавленное в очередь, должно отображаться в течение 5 секунд, а затем удаляться из состояния.

  • нулевое значение должно быть присвоено currentMessageId после последнего сообщение в очереди истекло
  • сообщение должно быть немедленно взято из очереди, если currentMessageId == null

Вот мое состояние:

import { EntityState } from '@ngrx/entity';

export interface UiMessage {
  id: string;
  severity: 'info' | 'warn' | 'error' | 'success';
  summary?: string;
  detail: string;
}
export interface MessagesState extends EntityState<UiMessage>{
   currentMessageId: string;
}

Я уже пробовал этот код, и он хорошо работает, если в магазине всегда было сообщение:

  takeMessageInterval$ = createEffect(() => {
    return timer(0, 5000).pipe(
      map(() => {
        return UiActions.takeNextMessage()
      })
    )
  });

, но рассмотрим такой сценарий:

  • Таймер эффекта запускается через секунду 0 в то время как в магазине нет сообщений
  • Сообщение добавляется в хранилище в секунду 1, затем сообщение должно ждать 4 секунды для отсчета времени, затем отображается в виде
    • Я хочу, чтобы оно отображалось как Быстро, насколько это возможно, и удалить через 5 секунд

также вот функция редуктора:

export const messagesReducer = createReducer<MessagesState>(
  initialState,
  on(UiActions.addStateMessage, (current, action) => {
    return messagesAdapter.addOne(action.message, current);
  }),
  on(UiActions.removeStateMessage, (current, action) => {
    return messagesAdapter.removeOne(action.id, current);
  }),
  on(UiActions.takeNextMessage, (current, action) => {
    // remove current message
    if (current.currentMessageId) {
      current = messagesAdapter.removeOne(current.currentMessageId, current);
    }

    // take next message id
    const nextId = current.ids[0] as string;
    current.currentMessageId = nextId;

    return current;
  }),
);

1 Ответ

0 голосов
/ 02 апреля 2020

Здесь может быть один подход, при условии, что одновременно может отображаться только одно сообщение:

takeMessageInterval$ = createEffect(
  () => this.actions$.pipe(
    // Intercept when a message has been added
    ofType(UiActions.addStateMessage),
    concatMapTo( // Queue up the messages
      timer(5000).pipe( // Display it for 5 seconds
        endWith(UiActions.takeNextMessage()) // Display the next message and remove the current one
      )
    )
  )
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...