我希望允许用户在我的代码生命周期中订阅事件,因此我已经包含了一个pubsub机制,一旦实例化了库,该机制就可供用户使用。它在大多数情况下运作良好。代码看起来像这样:
var library = function() {
//library code here
//Publish some sort of initialisation event
ev.publish('init');
//return an object that includes the ev pubsub functionality
};
然后我想象一个用户可能能够像这样进行交互:
var test = new library();
//the ev object is returned from the instantiation of the library
test.ev.subscribe('init',function() {});
这大部分都有效 - 订阅功能可以挂钩到所有帖子初始化发布。
问题在于实例化库并触发各种初始化事件。用户无法与初始化期间触发的发布事件进行交互,因为当用户有机会订阅任何已启动的启动事件时。
如何重构此代码以允许完整捕获事件系统?
答案 0 :(得分:1)
有几种方法可以实现这种目的。根据您的架构,要求和偏好,您可以执行以下任一操作:
方法1:
你可以接受一个回调函数作为init函数,你可以在那里处理它。
var library = function(initCallback) {
ev.subscribe('init', initCallback);
//library code here
//Publish some sort of initialisation event
ev.publish('init');
//return an object that includes the ev pubsub functionality
};
然后你可以像
一样打电话var test = new library(function() {});
方法2:
将init函数与实例化分开。这种架构最常用。您只能将所选方法公开为公开。
var library = function() {
//library code here
//Publish some sort of initialisation event
function init() {
ev.publish('init');
}
//return an object that includes the ev pubsub functionality
return {
init : init,
ev : ev,
// .... expose other function/properties
};
};
然后您可以使用它:
var test = new library();
//the ev object is returned from the instantiation of the library
test.ev.subscribe('init',function() {});
//Call the actual initialization
test.init();
方法3:
正如您所说,您不希望遵循上述两种方法,那么通过从对象移动事件处理程序,可能只有一种方法可以实现您想要的效果。由于您还未提供事件处理程序代码,因此我将使用jquery事件处理程序提供示例实现。
var library = function() {
//library code here
//Publish some sort of initialisation event
var self = this;
$(window).trigger( "init.library", [ self ] );
//return an object that includes the ev pubsub functionality
};
你可以这样使用:
$(window).on( "init.library", function( event, obj ) {
//Do whatever you want with "obj"
});
var test = new library();
如果你不想使用最后一种方法,那么祝你好运:)。如果您发现任何其他有趣的解决方案,请将其发布给其他人。实际上你可以做的另一件事,如果你的目的只是调用init函数,实例化对象(而不是实例化),那么你可以将ev.publish('init');
行更改为
setTimeout(function() {
ev.publish('init');
},1);
然后你的代码也会工作!!
快乐的编码!!
答案 1 :(得分:0)
我选择了一种使用队列数组的方法。如果发布者被解雇且没有相应的订阅者,则将发布添加到挂起的数组中。然后,任何新添加的订阅者都会检查挂起的数组,如果有匹配的发布条目,则触发订阅者回调。
var uid, topics, pending = {};
uid = 0;
topics = {};
subscribe = function (topic, fn) {
if (!topics.hasOwnProperty(topic)) {
topics[topic] = {};
}
topics[topic][++uid] = fn;
for(var key in pending) {
if(pending[key] === topic) {
delete pending[key];
for (key in topics[topic]) {
topics[topic][key](topic);
}
}
}
};
publish = function (topic, obj) {
var key;
if(!topics.topic) {
pending[topic] = topic;
}
if (topics.hasOwnProperty(topic)) {
for (key in topics[topic]) {
topics[topic][key](topic, obj);
}
}
};
publish('that');
subscribe('that',function() {console.log('hi')});