Метеор: Tracker.autorun и dep.change вызывают бесконечный цикл
Я использую новый 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 ответ
Проблема в том, что вы создаете круговую зависимость. Я бы порекомендовал использовать 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 знает, что не нужно отправлять два одинаковых запроса на подписку.