JavaScript Pub / Sub属性访问问题

时间:2012-09-14 19:33:29

标签: javascript underscore.js publish-subscribe

我在这里遇到一个奇怪的问题,希望大家都能帮忙。

项目详情

我正在为包含pubsub.subscribe_once()方法的更大应用程序开发一个简单的pub / sub实现。此方法允许创建一次性订阅,这意味着创建了通用订阅,然后一旦正确的“发布”事件触发并且运行订阅回调,订阅将自行删除。

subscribe_once: function(topic, func) {
    var sub = pubsub.subscribe(topic, func),
        old_func = sub.func;

    // rewrite our subscription's method to remove itself after invocation
    sub.func = function() {
        // call the original function
        old_func.apply(this);
        // remove subscription from topic
        pubsub.unsubscribe(sub);
    };

    return sub;
}

问题

我似乎对此过程的内存流有某种问题。 (为了最好地理解以下解释,我建议你在我去的时候通过下面的jsfiddle演示。)我创建了一个subscribe_once('someevent')订阅,然后激活发布('someevent')。调用publish方法时,您希望看到的主题哈希表包含一个“someevent”键,该键引用一个Subscription对象数组。事实上,如果您引用主题[“someevent”],您会看到一个包含单个订阅的数组。但是,如果您引用主题,则会看到“someevent”键,但数组为空!

通过注释掉pubsub.unsubscribe(sub);,问题就消除了,即使在我们运行console.log(topics)之后这个功能似乎没有被触发。

此外,对于给定浏览器“线程”console.log的方式,这似乎不是问题;尝试console.log(topics, topics[topic], topics, topics[topic]),你会得到相同的结果。

演示:http://jsfiddle.net/4Ab6c/

任何帮助都将非常赞赏!感谢。

1 个答案:

答案 0 :(得分:2)

我仍在寻找一些文档来支持我,但我怀疑控制台中的对象显示是对topics对象进行延迟评估。在将console.log(topics)推送到阵列后,我将subscribe添加到sub方法,我得到的结果与“但不在这里”的日志相同。当我在pubsub.publish('someevent')中包装你的小提琴setTimeout的最后一行并且在publish回调运行之前打开对象树时,它会在数组中显示订阅并且它保持这种状态即使在回调运行之后。如果我在回调运行之前没有在控制台中打开对象树,那么我会看到空数组。

我将继续搜索博客文章或确认正在进行懒惰评估的内容。

为了防止我没有明显表达,懒惰我的意思是,在控制台中单击树视图之前,控制台不会收集对象的详细信息。

我在Chrome上工作。

<强>更新

我在Firefox上也发现了类似的行为。 Firefox认识到数组中有一个对象,但是如果在发布甚至触发之前没有深入到数组中,那么数组上的向下钻取将为空。

我从你的评论中更新了小提琴:

http://jsfiddle.net/4Ab6c/2/

请试试这个:

  • 在发布事件触发之前运行小提琴并展开第一个console.log的对象树,我将其设置为五秒钟超时,但你可以根据你可以多快下来的时间来更长或更短到控制台并单击检查器打开。

  • 您应该按预期在数组中看到subscribe对象。

  • 清除控制台并再次运行小提琴。这次没有打开对象检查器,直到发布事件被触发并且所有代码都已运行完毕。

  • 现在,当您打开第一个console.log的对象检查器时,您不应该在数组中看到订阅事件。

更新2 这是一个更简单的小提琴,表现出相同的行为:

http://jsfiddle.net/4Ab6c/3/

如果你在第二次出现之前先展开,那么你将获得foo:bar。如果你在第二次出现后首先展开,你会得到foo:baz。

更新3

并且,瞧,another SO question秒对懒惰评估的动议。