Meteor ReactiveDict不会在第一次插入时触发事件

时间:2015-05-07 02:48:13

标签: javascript meteor

我将一段代码从会话迁移到 ReactiveDict 。经过一些调试后,当{key:value}对添加到字典中时,ReactiveDict不会触发任何重新计算事件。

var selected = new ReactiveDict()
  Meteor.autorun(function() {
    for (var k in selected.keys)
      console.log("reactiveDict", k, " : ", selected.get(k))
})

Meteor.setTimeout(function () { selected.set('test', true) }, 1000)
Meteor.setTimeout(function () { selected.set('test', false) }, 2000)
Meteor.setTimeout(function () { selected.set('test', true) }, 3000)
Meteor.setTimeout(function () { selected.set('test', false) }, 4000)

该代码不会打印任何内容,而以下工作

Meteor.autorun(function() {
    for (var k in Session.keys)
        console.log("session", k, Session.get(k))
})

Session.set('test', true)

它打印“会话测试为真”(会话在客户端更新中保存,因此需要确保以新的环境开始以使测试有效)

我的理解是ReactiveDict是Session的替代品(实际上是Session的代码可用于包中)。但在这种情况下,他们的表现非常不同。

我发现的唯一解决方法是使用已经存在的人工变量强制反应触发器

var selected2 = new ReactiveDict()
selected2.set('workaround', false)

Meteor.autorun(function() {
  for (var k in selected2.keys)
  {
    var v = selected2.get(k)
    if (k != "workaround") console.log("selected2", k, " : ", v)
  }
})

var selected2_set = function (key, value) {
  var w = (selected2.keys[key] == undefined)
  selected2.set(key, value)
  if (w) {
    selected2.set('workaround', true)
    selected2.set('workaround', false)
  }
}

Meteor.setTimeout(function () { selected2_set('test', true) }, 1000)
Meteor.setTimeout(function () { selected2_set('test', false) }, 2000)
Meteor.setTimeout(function () { selected2_set('test', true) }, 3000)

打印“selected2 test:true”,然后为false,然后为true

我的问题是

  • 是ReactiveDict观察到的一个功能还是一个bug?
  • 有更好的解决方法吗?

我想到的解决方法的唯一“改进”是允许“变通办法”在true和false之间切换,但这会产生其他类型的问题,例如无法迭代只是寻找真正的值。

此外,必须注意不要过滤“解决方法”,因为这样就不会正确触发重新计算。例如,自动运行中的以下更改不起作用,因为get('workaround')永远不会运行。

if (k != "workaround") console.log("selected2", k, " : ", selected2.get(k))

1 个答案:

答案 0 :(得分:2)

keys只是ReactiveDict的一个属性,并且不会注册一个被动依赖项,所以这种行为是预期的。在current implementation(流星v1.1)中,没有一种简单的方法可以实现你想要的目标。

upcoming version中,all会对所有密钥设置一个被动依赖项,因此这将有效:

Tracker.autorun(function() {
  _.each(selected.all(), function(value, key) {
    console.log(key + ":" + value);
  });
});

如果您现在要使用该版本,可以将源代码下载到名为lib/reactive-dict2.js的文件中,并将ReactiveDict的任何引用替换为ReactiveDict2(目前第19行和第43行 - 注意这很关键或应用程序的其他部分可能会中断)。然后你可以这样做来使用它:

var selected2 = new ReactiveDict2()

以上代码应该有效。