很长一段时间里,我一直在致力于为某客户开发大型Web应用程序。为web前端实现发布/订阅式通信,我们使用在body元素上被触发的jQuery自定义事件。这是一个相当巧妙的方法,以确保模块松耦合,因为你事实上只是跟踪用户做什么,而不是哪个模块生成的消息。
这种方法已经被我介绍给我的团队,而且我一直很热心地帮助我的队友知道如何使用它。
我对这个方法一直很满意,我已经在BerlinJS讨论组中发起了一个讨论。其他一些人也已采取这种方法,有些已在脚注中列出。
最近,我对这种方法越来越不满意了。
在使用jQuery自定义事件进行发布/订阅时你最终会遇到其中一个问题,就是它们是同步的,所以你最终会在你对当前事件结束操作之前触发新的事件。
它会变得很乱,相信我。嗯,其实有很多原因,最终使我在用JavaScript做发布/订阅中消息时寻找更好的方法。
我想要的东西将满足下列大部分的要求:那么,事实证明,我在互联网上搜索空手而归(我的Google-fu应该更好),所以我决定亲自写一个实现。我把它叫做PubSubJS。
我已经把它发布在http://github.com/mroderick/PubSubJS,你可以轻松得到它,如果你喜欢就运行测试,甚至通过扩展而为它做出贡献。
不是很多。
基本上,你可以订阅的息,发布消息(通过一个绑定项)和消息退订。如果你喜欢冒险的感觉(或你真的相信已经100%的理解库的前因后果),你也可以用同步方式强制发布消息。
让我们来看看一些写好的代码!
// subscribing to messages is quite easy,
// first we'll create a subscriber function
var logToConsole = function( message, data ){
// once a message arrives, it'll get logged to the console
// data passed in messages can be whatever you want
console.log( message, data );
};
// every subscription gives you a token,
// you should keep it if you want to unsubscribe
var token = PubSub.subscribe( 'some message', logToConsole );
// publishing messages is also quite easy
PubSub.publish( 'some message', 'hello world!' );
// now let's unsubscribe from this message
//(译者注,需要注释掉下面代码,保持订阅,才可在控制台看到输出结果)
PubSub.unsubscribe( token );
为了说明利用JavaScript和JavaScript + DOM在执行速度方面的不同,我创建了一个JSPerf.com 测试页面,就是compares PubSubJS performance to jQuery custom events。你可以去试一下。
不!… 当然,也许 …
如果你正在构建较大的web应用程序,而且需要在模块/组件/构件等之间具有松耦合,那么发布/订阅可能是你要寻找的答案。如果在你构建较大的web应用程序时碰巧使用Dojo并需要发布/订阅,那么我建议你看一下早在Dojo的实施方案,或联系Rebecca Murphey ;-)
想想看:发布/订阅有点像炸药。在考虑周全的专家之手,你可以期望在合理的时间内有安全地拆除一幢摩天大楼。在业余爱好者手中,使用炸药,你最终会看到最不想看到的,在一片非常嘈杂而凌乱的情况下告终。而且可以肯定,每过一段时间,就算是专家也会犯错误。
“那么为什么还要写一个发布/订阅库?”你可能会问,而得到的答案很简单:我需要它,就像爆破专家需要获得高效、稳定和可预测的炸药。写PubSubJS后,我发现Peter Higgins已经为jQuery实现了发布/订阅。
/*-----------------------------------------------------分割线------------------------------------------------------------*/
首次翻译,借助Google翻译进行辅助,比较拙略,难免有不尽人意的地方,还请大家多多包涵!O(∩_∩)O~
原文地址:roderick.dk/2010/10/12/introducing-pubsubjs-a-library-for-doing-publish-subscribe-in-javascript/