PubSub的性能成本/ JavaScript中的过多事件和事件处理程序?

客户端/服务器端JavaScript世界中的客户端/ 事件驱动架构是一种常见的做法。 我的任务是使用Dojo作为前端, node.js作为后端来构build一个非常大的Web应用程序。 酒吧/小组似乎非常吸引人,因为它允许团队之间的大量平行。 我恐怕,如果会有performance的后果。

我有一个关于JavaScript中的事件和事件处理程序的成本的一般问题。 我已经看到了这个 , 这个 ,甚至这个和这个 。 但是我似乎还没有看到一个通用的答案。 独立于框架,假设我们有两种方法

publish() //Like jQuery's / Dojo's trigger(), EventEmitter's emit() 

 subscribe() //Like jQuery's / Dojo's / EventEmiter's / DOM's on() connect() live() addEventListener() 

问题1:每个事件触发器的成本是多less?

案例1:清理(松耦合)强调Pub / Sub的代码

 object.publish('message1', data); object.publish('message2', data); ... object.publish('message100', data); //All these are in separate files / modules subscribe (object, 'message1', function (data) { A()...}) subscribe (object, 'message2', function (data) { B()...}) subscribe (object, 'message100', function (data) { Z()...}) 

情况2:紧密耦合的代码! 但是它更高性能

 data.message = 'message1' object.publish('message', data) subscribe (object, 'message', function (data) { switch (data) { case 'message1': A(); break(); case 'message2': B(); break(); ... case 'message100': Z(); break(); } }) 

问题2:每个Event侦听器的成本是多less?

 object.publish('event', data); 

案例1:再次强调Pub / Sub的清理(松散耦合)代码

 //A.js subscribe (object, 'event', function (data) { A(); }); //B.js subscribe (object, 'event', function (data) { B(); }); //C.js subscribe (object, 'event', function (data) { C(); }); 

案例2:再一次,紧密耦合的代码! 但是它更高性能?

 subscribe (object, 'event', function (data) { A(); B(); C(); }); 

Q1:有人能指向我在客户端(使用DOMEvents或自定义事件),服务器端(Node.js中的EventEmitter等)进行的研究和性能testing吗? 它是一个简单的例子,但可以很容易地增长到1000这样的电话 ,应用程序是相当大的。 如果不是,我该如何去评估自己是否明显的性能下降? 也许像jsperf的东西? 认识一号公路的任何理论基础都比另一个更高效。

Q2:如果Case 1更高性能,写松耦合代码的最好方法是什么? 任何find中间立场的方法? 编写类似案例1的代码,但是一些中间编译/构build过程将其转变为案例2 (类似于Google Closure编译器在其他情况下所做的)?使用[Esprima]说。 我讨厌把构build过程复杂化得比现在更复杂。 性能提升(如果有的话)是否值得所有这一切?

Q3:最后,尽pipe我在这里寻找一个非常特定的JavaScript特定的答案,但它可能有助于了解其他语言/环境中的性能成本。 在大多数情况下,事件是硬件触发(使用中断的概念)的事实有助于答案?

感谢所有的人,直到这个问题的结束! 非常感激!!!

       

网上收集的解决方案 "PubSub的性能成本/ JavaScript中的过多事件和事件处理程序?"

您所build议的每个体系结构决策都会对性能产生影响:


回电话

一对一的绑定,直接引用了该函数

酒吧子活动

一对多的绑定,需要一个循环来调用多个callback,更多的callback=更差的性能

承诺

使用延迟来确保链中的每个项目不被同时调用,更多的链条=更差的性能


我会select大多数情况下的callback,除非你有一个负载相互连接的模块,然后pub / sub是有用的。

请记住,这些可以互相协同工作。 我通常在同一个模块中允许一个callback和一个pub / sub事件,让开发者select他们喜欢使用哪一个:

 var module = { events: [], item: { 'name': 'Test module' }, updateName: function(value, callback) { this.item.name = value; if (callback) { callback(this.item); } this.dispatchEvent('update', this.item); }, addEvent: function(name, callback) { if (!this.events[name]) { this.events[name] = []; } this.events[name].push(callback); }, removeEvent: function(name, callback) { if (this.events[name]) { if (callback) { for (var i=0; i<this.events[name].length; ++i) { if (this.events[name][i] === callback) { this.events[name].splice(i, 1); return true; } } } else { delete this.events[name]; } } }, dispatchEvent: function(name, data) { if (this.events[name]) { for (var i=0; i<this.events[name].length; ++i) { this.events[name][i]({ data: data, target: this, type: name}); } } } }; module.updateName('Dan'); // no callback, no event module.updateName('Ted', function (item) { console.log(item); }); // callback, no event module.addEvent('update', function (item) { console.log(item); }); // add an event module.updateName('Sal'); // no callback, event callback module.addEvent('update', function (item) { console.log('event2', item); }); // add a second event module.updateName('Jim'); // no callback, two event callbacks