Meteor:Tracker.autorun和dep.changed导致无限循环

时间:2014-12-02 00:07:05

标签: meteor meteor-tracker

我正在使用一个新的Tracker.Dependency来跟踪几件事情,但它会导致下面代码中的自动运行无限运行。怎么了?一旦我将getSong和getSongId分开依赖于dep和dep2而不仅仅是dep,下面的代码是可以的。

SongManager = {
  dep: new Tracker.Dependency,
  dep2: new Tracker.Dependency,
  init: function(songId) {
    var self = this;
    this.setSongId(songId);
    Meteor.subscribe('song', songId);
    Tracker.autorun(function(){
      var songs = self.getSongCursor().fetch();
      if (songs.length > 0) {
        self.song = songs[0];
        self.dep.changed();
      }
    })
  },
  getSongCursor: function(){
    return Songs.find({_id: this.getSongId()});
  },
  getSong: function(){
    this.dep.depend();
    return this.song;
  },
  getSongId: function(){
    this.dep2.depend();
    return this.songId;
  },
  setSongId: function(arg){
    this.songId = arg;
    this.dep2.changed();
  },
};

1 个答案:

答案 0 :(得分:3)

问题在于您正在创建循环依赖项。我建议使用ReactiveVar而不是使用较低级别的依赖项API。

meteor add reactive-var

然后你可以这样做:

SongManager = {

  song: new ReactiveVar(),

  songId: new ReactiveVar(),

  init: function(songId) {
    this.songId.set(songId);
    this.computation = Tracker.autorun(_.bind(this.update, this));
  },

  update: function() {
    var songId = this.songId.get();
    Meteor.subscribe('song', songId);
    this.song.set(Songs.findOne(songId));
  },

  stop: function() {
    this.computation.stop();
  }
};

SongManager.init(oldSongId);
SongManager.songId.set(newSongId);

// After enough time has passed for the subscription to update and tracker to flush:
var currentSong = SongManager.song.get();
console.log(currentSong._id === newSongId); // true

我还为你添加了一种停止自动运行计算的方法,这样当它不再需要时它就不会在后台继续运行。请注意,由于订阅是在自动运行中运行的,因此当songId更改时,它将自动停止并重新启动。更新功能实际上将运行两次,但Meteor知道不发送两个相同的订阅请求。