MobX已计算–计算值链的对帐

时间:2019-01-28 12:47:54

标签: observable mobx computed-observable

关于“计算”的最佳实践,我有三个相关的问题。

TL; DR:我需要考虑一下自己以及和解开箱即用。

假设我将大量数据集加载到数据变量中:

data = asyncComputed( await fetch … return data )

然后我便有了方便计算的道具来格式化该数据:

@computed get timeseries() {
    const data = this.data.get()

    const timeseries = nest()
      .key(d => d.geo)
      .entries(data)

    return timeseries
  }

第三个方便的道具是根据时间序列计算的:

  @computed get extentX() {
    const timeseries = this.timeseries.get()
    const extentX = extent(timeseries, d => d.time)
    return extentX
  }
  1. 是否存在在所有这些计算完成之前进行渲染的风险,或者MobX是否确保之前对此进行了协调?

  2. 是否有更好的方法来构造此代码,以避免链接已计算的道具?

  3. 比方说,当对象上的属性(id)发生更改并随后从同一事件链更新该对象时,将触发第一个异步操作:


variable = { id : “my-variable”, extent: undefined} 

data = asyncComputed( await fetch api?id=variable.id ) 

=>计算范围=>结果为variable.extent = [200,400] 是否有可能引发无限循环的风险,或者像这样更新对象属性是否安全?

2 个答案:

答案 0 :(得分:1)

这是我对此主题的看法。

  1. Mobx同步运行所有计算(Prof see Synchronous execution
  2. Mobx进行惰性评估(Prof see Lazy versus reactive evaluation
  3. 应用@observer时,它只是将渲染函数包装在autorunProof)中

从#1可以得出一个结论,如果我们有一个计算链,它们将像observable -> computed 1 -> computed 2

那样被同步求值。

从#2可以说,为了产生副作用-此计算链必须以自动运行observable -> computed 1 -> computed 2 -> autorun结尾

这已经使我们指向第3点。 @observer是一个HOC,可将您的Component包裹起来并在需要重新呈现时进行控制。现在,这不受组件的控制。

所以回答您的问题:

  1. 在计算的计算之间不会发生渲染。它会在最后一个computed调用autorun
  2. 之后发生
  3. computed的束缚是一种强大的方法,应该避免使用它,而应谨慎使用。

来自文档:

  

通过构成反应式计算,甚至可以将一个数据图自动转换为另一数据图,并以最少的补丁数保持此推导最新。这样可以轻松实现复杂的模式,例如映射减少,使用不可变共享数据的状态跟踪或横向数据加载。

  1. Mob具有防止循环的功能。您将看到一个控制台错误,即不允许更改带有流的可观察变量

答案 1 :(得分:0)

以我的经验,在其他“计算的”值之上构建MobX“计算的”值既简单又健壮,并且是将复杂的数据转换分解为逻辑和可测试的婴儿步骤的一种非常有效的方法。

使用一系列“计算”时,每个步骤都是在先前结果的基础上进行数据转换的,每个步骤都有一个名称。因此,每个步骤的结果就是一个可观察到的名称,您的应用可以查看或显示在屏幕上。这样可以轻松地分别编写,测试和调试每个步骤。

在运行时,您的顶级“计算”获得与简单“计算”相同的神奇效率​​和重新计算,因此实际上没有不利之处。我强烈推荐它。