Javascript 在实例化库时,订阅服务器无法侦听启动事件

Javascript 在实例化库时,订阅服务器无法侦听启动事件,javascript,design-patterns,refactoring,publish-subscribe,Javascript,Design Patterns,Refactoring,Publish Subscribe,我希望允许用户订阅代码生命周期中的事件,因此我包含了一个pubsub机制,该机制在库实例化后立即提供给用户。它在大多数情况下运行良好。代码如下所示: var library = function() { //library code here //Publish some sort of initialisation event ev.publish('init'); //return an object that includes the ev pubsu

我希望允许用户订阅代码生命周期中的事件,因此我包含了一个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() {});
这在很大程度上是有效的-subscribe函数可以连接到所有初始化后发布

问题在于何时实例化库以及何时触发各种初始化事件。用户无法与初始化期间触发的发布事件交互,因为当用户有机会订阅任何已触发的启动事件时


如何重构此代码以允许完整捕获事件系统?

有几种方法可以实现这类功能。根据您的体系结构、需求和偏好,您可以执行以下任一操作:

方法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();
$(window).on( "init.library", function( event, obj ) {

//Do whatever you want with "obj"

});

var test = new library();
方法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 

};
然后你可以像这样使用它:

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();
$(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);
那么你的代码也会工作


快乐编码

我决定采用一种使用队列数组的方法。如果触发了发布服务器,但没有相应的订阅服务器,则该发布将添加到挂起的数组中。然后,任何新添加的订阅服务器都会检查挂起的数组,如果有匹配的发布条目,则触发订阅服务器回调


谢谢是的,我已经考虑过这两种方法,但我真的不想让订阅服务器作为param输入或添加init函数。实现这一点的唯一方法是,将事件处理程序移出对象。类似jQuery事件处理程序的东西谢谢您的编辑-这些都是很好的建议。不过,我也不喜欢jQuery解决方案,因为我需要控制上下文。可能有许多图书馆使用pubsub的实例,因此我需要将事件与实例联系起来。我决定采用排队制。如果为没有订阅服务器的事件进行发布,则会将其添加到挂起的数组中。注册订阅服务器时,它会检查挂起的数组-如果有匹配的条目,则会触发订阅服务器回调。现在只是起草一个答案……jQuery解决方案将上下文作为参数提供给您。我已经告诉您这是事件处理程序的一个示例实现,您所做的是第三种方法的实现:)。很高兴您终于解决了问题。实际上,您的实现不起作用!!如果你在订阅后发布你的活动,直到它不起作用,就像以前一样!!看,是的,但基本方法是存在的。我得把它整理一下。当答案为100%时,我将更新答案