【问题标题】:How to queue actions through time properly when using redux-observables使用 redux-observables 时如何正确地对动作进行排队
【发布时间】:2018-03-24 18:08:16
【问题描述】:

我正在尝试创建一个 Epic,将要调度的操作排队,在这种情况下,这些操作是要使用快餐栏显示的消息,例如,三个错误几乎同时发生,我想显示三个带有 SnackBar 的错误消息,Epic 应该调度一个动作来显示第一个 3 秒,然后显示第二个 3 秒,然后显示第三个 3 秒。

此外,如果其中一个小吃店关闭,则应显示“队列”中的第二个,依此类推。我现在正在做的是调度在 Epics 中显示捕获错误的消息的动作,然后我正在创建 Epics 调度动作以在延迟 3 秒后关闭小吃店,并使用动作 CLOSE_SNACKBAR。我应该使用哪些方法来实现这一目标?

我实现的基本 Epic 看起来像这样,基本上将状态从小吃栏更改为打开并显示错误消息的操作是从另一个 Epic 分派的,即捕获错误的那个,然后另一个 Epic 分派3 秒后关闭小吃栏的操作,但我还没有弄清楚如何执行这种排队类型的操作,以便每条消息可以显示 3 秒,现在如果在第一个错误之后发生错误,第二个在上一条消息之后的 3 秒内将显示消息。 以下是我的史诗的一些基本示例(忽略请求部分,):

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 请求,但如果它们失败,它们会调度打开带有错误消息的快餐栏的操作,并且两个错误消息是不同的。

而这个就是目前3秒后关闭Snackbar的史诗:

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 秒,

【问题讨论】:

  • 您能否重新措辞/详细说明您的问题?
  • 我已经重新阐述了这个问题,希望现在问题更清楚了

标签: rxjs react-redux redux-observable


【解决方案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 操作。动作中应该包含一个唯一的 ID,用于跟踪需要关闭的消息。

最后,使用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))
    );
  });

【讨论】:

    猜你喜欢
    • 2017-05-11
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 2021-03-24
    • 1970-01-01
    • 2018-11-24
    相关资源
    最近更新 更多