如何使用redux observable创建一个简单的通知系统?

如何使用redux observable创建一个简单的通知系统?,redux,rxjs,observable,redux-observable,Redux,Rxjs,Observable,Redux Observable,我试图用redux observable做一个简单的通知系统。我是新来的rxjs,所以我很难做到这一点 我想做的是: 发送显示通知的意图 使用Epic 分派插入新通知的操作 等3秒钟 分派另一个删除旧通知的操作 这是我的史诗: import { NOTIFICATION_DISPLAY_REQUESTED } from '../actions/actionTypes'; import { displayNotification, hideNotification } from '../actio

我试图用redux observable做一个简单的通知系统。我是新来的
rxjs
,所以我很难做到这一点

我想做的是:

  • 发送显示通知的意图
  • 使用
    Epic
  • 分派插入新通知的操作
  • 等3秒钟
  • 分派另一个删除旧通知的操作
  • 这是我的史诗:

    import { NOTIFICATION_DISPLAY_REQUESTED } from '../actions/actionTypes';
    import { displayNotification, hideNotification } from '../actions/notifications';
    
    export const requestNotificationEpic = (action$, store) =>
      action$.ofType(NOTIFICATION_DISPLAY_REQUESTED)
        .mapTo(displayNotification(action$.notification))
        .delay(3000)
        .mapTo(hideNotification(action$.notification));
    
    实际发生的情况是发出所请求的
    NOTIFICATION\u DISPLAY\u
    ,3秒钟后发出
    hideNotification
    <代码>显示通知从未发生过

    我可以从视图中发送
    displayNotification
    ,延迟3秒,然后发送
    hideNotification
    。但是,如果有3个以上的活动通知,我想在添加新通知之前删除最后一个通知。这就是为什么在这个简单的例子中,我从epic内部手动分派
    displayNotification

    那么,我如何做到这一点呢?对不起,如果这是一个超级简单的问题,我只是一个新手,需要一些帮助


    注意:我知道
    redux传奇存在,只是
    redux obsevable
    对我来说更有意义。

    如果你是RxJS新手,这并不是那么简单:)

    提前做好几件事:

    操作员链 Epic是一个函数,它接受一系列动作并返回一系列动作。动作进,动作出。链接以转换匹配操作的函数称为运算符。链接操作符很像链接花园软管或电源线——值从一个流向另一个。它也非常类似于只链接常规函数,如
    third(second(first())
    ,不同的是,可观察对象有一个额外的时间维度,因此操作符应用于流经它们的每个值

    因此,如果你说
    stream.mapTo(x).mapTo(y)
    ,那么当你
    .mapTo(y)
    时,你第一次映射到
    x
    的事实就变得毫无意义了,因为
    mapTo
    忽略了源代码的值,而只是将它映射到提供的值

    如果改为使用
    map
    ,它可能会变得更加明显:

    stream.map(value => 'a message').map(message => message + '!!!')
    
    更确切地说,操作符的链接是RxJS,而不是特定于redux observable,这更像是一种在redux中使用少量胶水的模式

    动作$
    是可观察的(技术上可观察的动作) 参数
    action$
    是可观察到的操作,而不是实际操作本身。因此,
    action$。通知将是
    未定义的
    。这就是人们通常使用美元符号后缀的原因之一,表示它是一系列的东西

    只考虑2个动作,而不是3个动作。 您的示例显示了使用三个动作
    通知\u显示\u请求的
    和另外两个动作来显示和隐藏通知。在这种情况下,原始意图操作基本上与
    displayNotification()
    相同,因为它将在另一个操作之后同步调度

    考虑只有两个操作,一个用于“显示此通知”,另一个用于“隐藏此通知”。虽然这不是规则,但它通常可以简化代码并提高性能,因为简化程序不必运行两次

    这就是您的案例中的情况(当然,请说出您喜欢的名称):

    然后,您的减速器将收到
    显示\u通知
    ,然后在3秒钟后
    隐藏\u通知
    (订购任何东西)

    此外,请记住rom:

    记住:在减速机已经收到EPIC后,EPIC沿着正常的Redux调度通道运行。当您将一个动作映射到另一个动作时,您并没有阻止原始动作到达减速器;这一行动已经通过了他们

    解决方案 虽然我建议在这种情况下只使用两个动作(见上文),但我确实想直接回答您的问题!因为RxJS是一个非常灵活的库,所以有很多方法可以满足您的要求

    这里有几个:

    一部史诗,使用concat 订阅用于一次订阅所有提供的可观察对象,仅当当前一个完成时才移动到下一个。它一次“消耗”每一个可观察到的

    如果我们想要创建一个发出一个动作的流,等待3000毫秒,然后发出另一个动作,您可以这样做:

    Observable.of(displayNotification(action.notification))
      .concat(
        Observable.of(hideNotification(action.notification))
          .delay(3000)
      )
    
    或者这个:

    Observable.concat(
      Observable.of(displayNotification(action.notification)),
      Observable.of(hideNotification(action.notification))
        .delay(3000)
    )
    
    在这种情况下,它们具有完全相同的效果。关键是我们要将
    延迟
    应用于与第一个不同的可观察对象,因为我们只想延迟第二个动作。我们孤立他们

    要在epic中使用,您需要一个合并策略操作符,如
    mergeMap
    switchMap
    ,等等。学习这些非常重要,因为它们在RxJS中经常使用

    export const requestNotificationEpic = (action$, store) =>
      action$.ofType(NOTIFICATION_DISPLAY_REQUESTED)
        .mergeMap(action =>
          Observable.concat(
            Observable.of(displayNotification(action.notification)),
            Observable.of(hideNotification(action.notification))
              .delay(3000)
          )
        );
    
    两部不同的史诗 另一种方法是创作两部不同的史诗。一个负责将第一秒映射到第二秒,另一个负责在隐藏前等待3秒

    export const requestNotificationEpic = (action$, store) =>
      action$.ofType(NOTIFICATION_DISPLAY_REQUESTED)
        .map(action => displayNotification(action.notification));
    
    export const displayNotificationEpic = (action$, store) =>
      action$.ofType(DISPLAY_NOTIFICATION)
        .delay(3000)
        .map(action => hideNotification(action.notification));
    
    这是因为史诗可以与所有的动作相匹配,即使是其他史诗发出的动作!这允许清洁分离、合成和测试

    这个例子(对我来说)更好地说明,对于这个例子来说,有两个意图的动作是不必要的,但可能有一些需求是你没有提供的


    如果这非常令人困惑,我建议首先深入研究RxJS。教程、视频、研讨会等。这只不过是表面现象,它会变得更深,但对于大多数坚持使用它的人来说,回报是巨大的。

    Hi@jayphelps(顺便说一句,我很喜欢你的演讲!)在你回答之前,我实际上是和
    concat
    操作员一起做的,所以我想我的思路是对的。这三个动作的原因是什么
    export const requestNotificationEpic = (action$, store) =>
      action$.ofType(NOTIFICATION_DISPLAY_REQUESTED)
        .map(action => displayNotification(action.notification));
    
    export const displayNotificationEpic = (action$, store) =>
      action$.ofType(DISPLAY_NOTIFICATION)
        .delay(3000)
        .map(action => hideNotification(action.notification));