垃圾回收如何处理 mobx-utils 中的异步操作?

How does garbage collection address async actions in mobx-utils?

我想要一个清晰的方法来创建商店,当我知道有新的服务数据可用时可以刷新(例如 lazyObservable 来自 mobx-utils),但可以轻松附加更多计算值和操作函数。

从create-react-app开始,使用这个index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {observable} from 'mobx';
import {observer} from 'mobx-react';
import {asyncAction} from 'mobx-utils';

const flipACoin = () => Math.random() > 0.5;

function determineGodliness() {
  const screwYourRAM = new Array(1000000).fill(Math.random());

  return new Promise((resolve) => {
    setTimeout(() => {
      resolve([flipACoin(), flipACoin()]);
    }, 1500);
  });
}

function godStore() {
  const store = observable({
    alpha: false,
    omega: false,
    waiting: false,
    refresh: asyncAction(function *() {
      this.waiting = true;
      [this.alpha, this.omega] = yield determineGodliness();
      this.waiting = false;
    }),
    get isGod() {
      return this.alpha && this.omega;
    }
  });

  store.refresh();

  return store;
}

window.store = godStore();

const App = observer(({store}) => <p>{
  (store.waiting)
    ? 'The suspense is killing me!'
    : (store.isGod)
      ? 'I am the Alpha and the Omega'
      : 'I just work here.'
}</p>);

ReactDOM.render(<App store={window.store} />, document.getElementById('root'));

每次您在控制台中 运行 window.store.refresh() 时,任务管理器都会显示内存使用量增加。有趣的是,使用 setInterval(window.store.refresh, 3000) 实际上会导致内存使用量波动而不是线性攀升。在这两种相互矛盾的情况下,我对垃圾收集器如何看待这种设置感到困惑。

我该怎么做才能绝对确定 screwYourRAM 最终会被垃圾回收?我只关心保留生成器返回的内容,而不是临时分配的内容。

仅通过查看内存图很难确定内存泄漏。 Afaik V8 不会总是释放所有内存,除非确实存在短缺(毕竟 GC-ing 是一种优化,过于积极地收集会节省内存,但会燃烧太多 CPU 周期。你不能假设 afaik空闲 VM 将自动释放所有内存)。所以我通常用一个保持 运行 并长时间重复一个过程的节点脚本来测试它,并且使用有限的内存来查看是否有东西真的泄漏了。

在您的示例中,据我所知/可以说,没有理由会出现内存泄漏。在某些时候,Promise 被 gc-ed,使得 gc 随之而来的闭包成为可能。 chrome 控制台将通过 $_ 保留对您的承诺的引用,这样也可以解释内存增加)

要正确查看是否存在内存泄漏,请使用 chrome / firefox 中的分析器,并确保强制执行 GC(chrome devtools 有一个按钮,FF 可能也是如此)