JavaScript发布/子属性访问问题
我在这里遇到了一个奇怪的问题,希望你们都能帮忙解决 项目详情 我正在为一个更大的应用程序开发一个简单的pub/sub实现,其中包括一个JavaScript发布/子属性访问问题,javascript,underscore.js,publish-subscribe,Javascript,Underscore.js,Publish Subscribe,我在这里遇到了一个奇怪的问题,希望你们都能帮忙解决 项目详情 我正在为一个更大的应用程序开发一个简单的pub/sub实现,其中包括一个pubsub.subscribe\u once()方法。此方法允许创建一次性订阅,这意味着创建了一个通用订阅,然后一旦触发正确的“发布”事件并运行订阅回调,订阅将删除自身 subscribe_once: function(topic, func) { var sub = pubsub.subscribe(topic, func), old_
pubsub.subscribe\u once()
方法。此方法允许创建一次性订阅,这意味着创建了一个通用订阅,然后一旦触发正确的“发布”事件并运行订阅回调,订阅将删除自身
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;
}
问题
我似乎对这个过程的记忆流有一些问题。(为了更好地理解下面的解释,我建议您边走边浏览下面的JSFIDLE演示。)我创建了一个subscribe_once('someevent')订阅,然后启动publish('someevent')。调用publish方法时,您希望看到的是topics哈希表包含一个“someevent”键,该键引用一个订阅对象数组。事实上,如果您引用主题[“someevent”],您会看到一个包含单个订阅的数组。但是,如果您引用主题,您会看到“someevent”键,但是数组是空的强>
通过注释出pubsub.unsubscribe(sub)代码>此问题已被消除,即使在运行console.log(topics)
之后才启动此函数
此外,这似乎与给定浏览器“线程”console.log的方式无关;尝试console.log(topics,topics[topic],topics,topics[topic])
会得到相同的结果
演示:
任何帮助都将不胜感激!谢谢。我仍在寻找一些文档来支持我,但我怀疑控制台中的对象显示正在对您的主题执行惰性评估。在将sub
推送到数组中之后,我将console.log(topics)
添加到subscribe
方法中,得到的结果与“但不在这里”日志相同。当我在setTimeout
中包装fiddlepubsub.publish('someevent')
的最后一行,并在publish
回调运行之前打开对象树时,它会在数组中显示订阅,即使在回调运行之后,它也会保持这种状态。如果在回调运行之前我没有在控制台中打开对象树,那么我会看到空数组
我会继续搜索一篇博客文章或是一些证实懒惰评估正在发生的事情
以防万一,我还没有说得很清楚,我所说的懒惰是指,在控制台中单击打开树视图之前,控制台不会收集对象的详细信息
我在Chrome工作
更新
我在Firefox上也发现了类似的行为。Firefox识别出数组中有一个对象,但是如果在发布偶数触发之前没有深入到数组中,那么对数组的深入将是空的
我根据您的评论更新了小提琴:
请试试这个:
- 运行fiddle并展开第一个console.log的对象树在发布事件触发之前,我将其设置为5秒超时,但您可以根据进入控制台并单击inspector open的速度将其设置为更长或更短
- 您应该在数组中看到预期的订阅对象
- 清理控制台并再次运行小提琴。这次不要打开对象检查器,直到发布事件触发并且所有代码都运行完毕
- 现在,当您打开第一个console.log的对象检查器时,您不应该在数组中看到订阅事件
更新2
这里有一个更简单的小提琴,表现出相同的行为:
若在第二个出现之前展开第一个,那个么将得到foo:bar。若你们在第二个出现后展开第一个,你们会得到foo:baz
更新3
瞧,这是关于延迟评估的动议。这将是一个严重的延迟评估:请参阅此更新,特别是文档底部的setTimeout环绕“unsubscribe”@即使没有支持文件,我也有一把小提琴,我认为它证实了正在发生的事情。见更新2。你完全正确。我想知道惰性评估中的值是多少?这似乎只会使跟踪对象的更改变得困难。请看下面的证据:@Squirkle我完全同意。这实际上在本周早些时候的一个主干应用程序上咬了我一口,尽管我直到研究了你的问题才意识到这是个问题。在另一个SO问题上提到的一种策略是将对象包装在JSON.stringify
中,这会导致对象作为log is run.dup of进行计算