Как правильно ставить в очередь действия во времени при использовании redux-observables

Я пытаюсь создать Epic, который ставит в очередь действия для отправки, в этом случае действия - это сообщения, которые должны отображаться с помощью закусочной, так что, например, три ошибки произошли почти одновременно, и я хочу отобразить три сообщения об ошибках с SnackBar Epic должен отправить действие для отображения первого в течение 3 секунд, затем отображения второго в течение 3 секунд, а затем третьего в течение 3 секунд.

Также, если одна из закусок закрывается, должна отображаться вторая в «очереди» и так далее. В данный момент я отправляю действие, которое отображает сообщение в эпиках, которые обнаруживают ошибки, затем я создаю эпики, отправляющие действие, чтобы закрыть закусочную после 3 секунд задержки, с действием CLOSE_SNACKBAR. Какие методы мне следует использовать для этого?

Базовый Epic, который я реализовал, выглядит так: в основном действие, которое изменяет состояние с закусочной на открытие и отображает сообщение об ошибке, отправляется из другого эпика, того, который обнаруживает ошибку, а затем другой Epic отправляет действие для закрытия закусочная через 3 секунды, но я не понял, как сделать это действие в очереди, чтобы каждое сообщение могло отображаться в течение 3 секунд каждое, прямо сейчас, если ошибка возникает сразу после первого, второе сообщение будет отображается без ожидания через 3 секунды после предыдущего сообщения. Вот несколько основных примеров моих эпиков (Ignore de request part,):

const getUserEpic = (action$, store) => (
    action$.ofType(actionTypes.DATA_REQUESTED)
        .switchMap(action => {
            const { orderData, queryData, pagerData } = store.getState().usuario.list;
            const params = constructParams(queryData, pagerData, orderData);
            return Observable.defer(() => axios.get(`users`, { params }))
                .retry(NETWORK.RETRIES).mergeMap(response => {
                        Observable.of(actions.dataRequestSucceeded(response.data.rows))
                }).catch(error => Observable.concat(
                    Observable.of(actions.dataRequestFailed(error)),
                    Observable.of({
                        type:'DISPLAY_DATA_REQUEST_FAILED_MESSAGE',
                        open:true,
                        message:'Failed to get Users Data'
                    })
            ));
        })
)
const getRoleEpic = (action$, store) => (
    action$.ofType(actionTypes.DATA_REQUESTED)
        .switchMap(action => {
            const { orderData, queryData, pagerData } = store.getState().usuario.list;
            const params = constructParams(queryData, pagerData, orderData);
            return Observable.defer(() => axios.get(`role`, { params }))
                .retry(NETWORK.RETRIES).mergeMap(response => {
                        Observable.of(actions.dataRequestSucceeded(response.data.rows))
                }).catch(error => Observable.concat(
                    Observable.of(actions.dataRequestFailed(error)),
                    Observable.of({
                        type:'DISPLAY_DATA_REQUEST_FAILED_MESSAGE',
                        open:true,
                        message:'Failed to get Roles Data'
                    })
            ));
        })
)

Эти два эпика в основном выполняют сем, они отправляют запрос GET на бэкэнд, но если они терпят неудачу, они отправляют действие, открывающее закусочную, с сообщением об ошибке, и оба сообщения об ошибках различны.

И это эпопея, которая в настоящее время закрывает Snackbar через 3 секунды:

const displayDataRequestFailedEpic = (action$, store) => (
    action$.ofType(actionTypes.DISPLAY_DATA_REQUEST_FAILED)
        .debounceTime(3e3)
        .switchMap( action => {
            return Observable.of({
                type:'CLOSE_SNACKBAR',
                open:false,
                message:''
            })
        })
)

Представьте, что я выполняю оба запроса очень быстро, и оба они терпят неудачу. Я хочу показать все произошедшие ошибки, одну за другой по 3 секунды каждая,


person sgaseretto    schedule 12.10.2017    source источник
comment
Можете ли вы перефразировать / уточнить то, о чем вы спрашиваете?   -  person jayphelps    schedule 13.10.2017
comment
Я переформулировал вопрос, надеюсь, теперь проблема прояснилась.   -  person sgaseretto    schedule 13.10.2017


Ответы (1)


Это не проверялось ...

Во-первых, необходимо отделить действие, которое отображает сообщения, от действия, вызывающего отображение:

const getUserEpic = (action$, store) => (
    action$.ofType(actionTypes.DATA_REQUESTED)
        .switchMap(action => {
            const { orderData, queryData, pagerData } = store.getState().usuario.list;
            const params = constructParams(queryData, pagerData, orderData);
            return Observable.defer(() => axios.get(`users`, { params }))
                .retry(NETWORK.RETRIES).mergeMap(response => {
                        return Observable.of(actions.dataRequestSucceeded(response.data.rows))
                }).catch(error => Observable.of(actions.dateRequestFailed(error))

                // }).catch(error => Observable.concat(
                //     Observable.of(actions.dataRequestFailed(error)),
                //
                // this will be handled elsewhere
                //
                //     Observable.of({
                //         type:'DISPLAY_DATA_REQUEST_FAILED_MESSAGE',
                //         open:true,
                //         message:'Failed to get Users Data'
                //     })
            ));
        })
)

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

Наконец, используйте concatMap() для создания и уничтожения сообщений.

const displayEpic = action$ => action$
  .ofType(actionTypes.DATA_REQUEST_FAILED)
  .concatMap(action => {
    const messageAction = actions.displayMessage(action);
    const { id } = messageAction;
    return Rx.Observable.merge(
      Rx.Observable.of(messageAction),
      Rx.Observable.of(actions.closeMessage(id))
        .delay(3000)
        .takeUntil(action$
           .ofType(actionTypes.CLOSE_MESSAGE)
           .filter(a => a.id === id))
    );
  });
person Robert Farley    schedule 21.11.2017