如何使用redux observable创建一个简单的通知系统?
我试图用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
rxjs
,所以我很难做到这一点
我想做的是:
Epic
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));