Appearance
必须先订阅再发布吗
我们所了解到的发布—订阅模式,都是订阅者必须先订阅一个消息,随后才能接收到发布者 发布的消息。如果把顺序反过来,发布者先发布一条消息,而在此之前并没有对象来订阅它,这 条消息无疑将消失在宇宙中。
在某些情况下,我们需要先将这条消息保存下来,等到有对象来订阅它的时候,再重新把消 息发布给订阅者。就如同 QQ 中的离线消息一样,离线消息被保存在服务器中,接收人下次登录 上线之后,可以重新收到这条消息。
这种需求在实际项目中是存在的,比如在之前的商城网站中,获取到用户信息之后才能渲染 用户导航模块,而获取用户信息的操作是一个 ajax 异步请求。当 ajax 请求成功返回之后会发布 一个事件,在此之前订阅了此事件的用户导航模块可以接收到这些用户信息。
但是这只是理想的状况,因为异步的原因,我们不能保证 ajax 请求返回的时间,有时候它返 回得比较快,而此时用户导航模块的代码还没有加载好(还没有订阅相应事件),特别是在用了 一些模块化惰性加载的技术后,这是很可能发生的事情。也许我们还需要一个方案,使得我们的 发布—订阅对象拥有先发布后订阅的能力。
为了满足这个需求,我们要建立一个存放离线事件的堆栈,当事件发布的时候,如果此时还 没有订阅者来订阅这个事件,我们暂时把发布事件的动作包裹在一个函数里,这些包装函数将被 存入堆栈中,等到终于有对象来订阅此事件的时候,我们将遍历堆栈并且依次执行这些包装函数, 也就是重新发布里面的事件。当然离线事件的生命周期只有一次,就像 QQ 的未读消息只会被重 新阅读一次,所以刚才的操作我们只能进行一次。