Tracker.autorun 如何挑选它的计算? [英] how does Tracker.autorun pick out its computation?

查看:26
本文介绍了Tracker.autorun 如何挑选它的计算?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看 Tracker.autorun,这主要是神奇的工作......但我想了解它如何决定哪些变量将形成计算的依赖关系.它只挑选反应性"变量,例如以下内容:

 window.bar = 1Tracker.autorun (c) =>bar = window.barfoo = Session.get('foo')console.log('autorun', foo, bar)

如果我更改 Session.set('foo') 的值,这将导致计算再次运行.而只是更改 window.bar 不会导致重新运行.如果我使用订阅结果(不是集合),这也有效,所以我猜也是反应性的.

是否有任何指南可以更好地理解这种行为?

感谢下面的评论澄清了计算是可以推断的,因为访问器用于响应式变量,因此meteor 可以跟踪 deps.

但是,我需要更清楚地了解何时标记了 var.例如在下面的这个例子中,subscribe 调用在 autorun 之外,但它把结果放入一个数组中.所以这意味着 Tracker 不仅跟踪对(reactive var)访问器方法的调用,还跟踪块内引用的任何变量 - 即使设置这些方法的调用在 autorun() 之外阻止.

 subList = [Meteor.subscribe("玩家"),Meteor.subscribe("东西")]Tracker.autorun (c) =>subReady = _.filter subList, (item) ->返回 item.ready()allDone = (subList.length == subReady.length)# 当 subs ready() 为真时,这段代码将重新运行

也许我应该将此添加为一个新问题...它与 这个问题 .

解决方案

我不是专家,也没有读过很多关于它的东西,但我可以试着简单地解释一下.

<小时>

所有反应性变量都有一个叫做依赖的东西.例如,当创建一个新的 ReactiveVar 时,就会创建一个新的依赖项.见这里.>

要从反应变量中检索值,必须调用一个函数.在那个getter"中,依赖项被指示记住它有一个依赖项.例如,见这里对于 ReactiveVar.get.

要更改反应变量的值,必须调用一个函数.在那个setter"中,依赖被通知某些东西已经改变了,这表明依赖于依赖的所有函数都必须重新运行.例如,见这里对于 ReactiveVar.set.

<小时>

不复杂吧?嗯,这只是简单的部分,现在剩下的就是构建使其工作的基础设施:) 这更难解释.

反应性变量本身不是反应性的;它们必须在反应性环境中进行评估才能具有反应性.通过调用 Tracker.autorun 创建反应式环境.参见此处.

当您调用 Tracker.autorun 时,您传递给它的函数将在一个新的响应式环境中执行,并且响应式变量通过 depend 通知的所有依赖项方法将被环境跟踪.当您调用 aDependency.depend 时,这个函数将被执行,它会在它所依赖的依赖项之上将依赖项添加到环境列表中.

当反应变量改变其值时,这个函数 将被执行.它告诉环境它所依赖的反应变量之一已经改变,并使环境中的所有依赖项失效.发生这种情况后,您传递给 Tracker.autorun 的整个函数将重新运行,并跟踪新的依赖项.

你有大局观吗?它的实现比我解释的要复杂一些,但我认为这就是它的工作原理.

Looking at Tracker.autorun, this mostly works magically...but I'd like to know how it decides which variables are going to form the dependency for the computation. It picks out only "reactive" vars, for example the following:

  window.bar = 1
  Tracker.autorun (c) =>
    bar = window.bar
    foo = Session.get('foo')
    console.log('autorun', foo, bar)

If I change the value of Session.set('foo') this will cause the computation to run again. whereas just changing window.bar doesn't cause a rerun. If I use a subscribe result (not a collection) this also works, so that I guess is reactive too.

Are there any guides to understanding this behavior a bit better?

EDIT:

thanks for the comments below that clarify the computation is able to be inferred because accessors are used for reactive vars, so meteor can track deps.

However I need a bit more clarity to understand when a var is flagged. for instance in this example below, the subscribe call is outside the autorun, but it puts the results into an array. So that means that Tracker is not just tracking calls to (reactive var) accessor methods, but also any variables that are referenced within a block - even if the calls to setup those methods are outside the autorun() block.

  subList = [
    Meteor.subscribe("Players"),
    Meteor.subscribe("Stuff" )
  ]

  Tracker.autorun (c) =>
    subReady = _.filter subList, (item) ->
      return item.ready()
    allDone = (subList.length == subReady.length)
    # this code will rerun when the subs ready() are true

maybe i should add this as a new question... it's related to this question .

解决方案

I'm not an expert and haven't read much about it, but I can try to explain it briefly.


All reactive variables have a thing called a dependency. For example, when one creates a new ReactiveVar, an new dependency is created. See here.

To retrieve the value from a reactive variable, one must call a function. In that "getter", the dependency is instructed to remember that it has a dependency. For example, see here for ReactiveVar.get.

To change the value for a reactive variable, one must call a function. In that "setter", the dependency is notified that something has changed, and that signals that all functions depending on the dependency must rerun. For example, see here for ReactiveVar.set.


Not complicated, right? Well, that was just the easy part, all that remains now is building the infrastructure that makes it work :) That's harder and more complicated to explain.

Reactive variables aren't reactive by themselves; they must be evaluated in a reactive environment in order to be reactive. A reactive environment is created by calling Tracker.autorun. See here.

When you call Tracker.autorun, the function you passed to it will be executed in a new reactive environment, and all dependencies the reactive variables notifies of with the depend method will be tracked by the environment. When you call aDependency.depend, this function will be executed, and it kind of adds the dependency to the environments list over dependencies it depends on.

When a reactive variable changes its value, this function will be executed. It tells the environment that one of the reactive variables it depends on has changed, and invalidates all the dependencies in the environment. After this has happened, the entire function you passed to Tracker.autorun will be re-run, and the new dependencies will be tracked.

Do you get the big picture? It's implementation is a bit more complicated than I've explained, but I think that's kind of how it works.

这篇关于Tracker.autorun 如何挑选它的计算?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆