是否可以减慢 Meteor 上的 Tracker 刷新速度?

Is it possible to slow down Tracker refresh on Meteor?

我有一个订阅了很多数据的应用程序,但我真的不需要实时加载它。是否可以让 Tracker 刷新数据更慢,比如 5 秒?我正在使用 React 进行开发并使用 withTracker()。谢谢!

Can it be possible to make Tracker refresh data slower, say 5 seconds?

Tracker 运行s 如果反应性数据发生变化,那么 Tracker(ReactiveVar、ReactiveDict、Subscription)中保存的数据的每一次变化都会导致重新运行。

... lot of data subscribed but I don’t really need it to be loaded in realtime.

那么你绝对应该删除订阅并通过 Meteor method.

获取你的数据

如果集合更新,发布立即向订阅者发送数据。如果你不依赖这个特性,基本上就是浪费服务器和网络资源,如果你的应用要达到更高层次的用户,资源就会成为一个大问题。

使用方法时,如果您连续多次调用它,将会产生一些数据开销,因为数据会再次从集合中发送(而发布仅发送增量),但您也可以控制这种行为好多了。

请注意,默认情况下您会失去反应性,但您可以将接收到的数据放入 ReactiveVar / ReactiveDict 或创建仅本地客户端 Mongo.Collection

如果您想保留使用 Mongo.Collection 的好处,您只需将收到的文档插入新的本地集合:

import { Mongo } from 'meteor/mongo'

const LocalCollection = new Mongo.Collection('myLocalData') // should have an own unique name or null

然后在 React 组件中调用方法(但不是 render 方法):

// call a Meteor.method, pass some arguments, if required
// and parse the resulting documents array.
Meteor.call('getMyDataFromMethod', {foo:'bar'}, (err, documents) => {
  if (err) {
    // handle err
  } else {
    documents.forEach(doc => {
      // update existing docs if present
      // or insert as new into local collection
      if (LocalCollection.findOne(doc._id)) {
        LocalCollection.update(doc._id, { $set: doc })
      } else {
        LocalCollection.insert(doc)
      }
    })
  }
}) 

由于您的文档已经包含 _id,因此它们将在插入本地集合时保留 _id

请注意,您的服务器方法需要 return 使用 find(...).fetch() 而不是游标来获取文档。

添加到本地集合后,您可以像在代码中一样使用它。

没有 built-in 方法来延迟 meteor 中的反应,

我可能有几种方法可以解决它

1) 就像@jankapunkt 说你可以使用 Meteor.methods 来提取数据然后你可以使用 Meteor.setInterval 每 5/10 秒调用相同的方法并更新数据

2) 如果你想使用 pub/sub 那么你可以订阅数据,一旦订阅准备就绪然后在 reactiveDictreactivieVar 变量中设置数据并且每 5 /10 秒 使用收集数据更新此变量并使用此变量显示 ui

中的数据

blaze 中第二个选项的示例代码,您可以在 react 中使用 setState 而不是 reactiveDict

import { Template } from "meteor/templating";
import { ReactiveDict } from "meteor/reactive-dict";

Template.myTemplate.onCreated(function() {
  const t = this;
  t.dataDict = new ReactiveDict();
  t.dataDict.set('users', []);
  t.subscribe('my.publication');
})

Template.myTemplate.hlepers(function() {
  users() {
    const t = Template.instance();
    return t.dataDict.get('users') || [];
  }
})

const startInterval = (t) => {
  t.interval = Meteor.setInterval(function() {
    const res = myCollection.find({}).fetch();
    t.dataDict.set('users', res);
  }, 5000);
};

Template.myTemplate.onRendered(function() {
  const t = this;

  t.autorun(function() {
    if (t.subscriptionsReady()) {
      const res = myCollection.find({}).fetch();
      t.dataDict.set('users', res);
      startInterval()
    }
  })
});

Template.myTemplate.onDestroyed(function() {
  const t = this;
  // clears interval
  Meteor.clearInterval(t.interval);
})