I have a problem when running with Meteor.
I have a "question" page which I want to increase the count view whenever it is rendered.
So in my template function I write
Template.questionview.helpers({
question : function() {
if(Session.equals('main_template_name', 'question')) {
console.log(Session.get('question_id'));
Questions.update({
_id: Session.get('question_id')
}, {
$inc: {
views: 1
}
});
}
});
Now here comes the problem, when I render the question view and update the question item, the view is refreshed again because it is a reflective page. And then it comes infinity loop.
Anyone has suggestions?
Typically, in situations like this, there is something broken about the model. In this case, I believe it's the "count view" idea. There are lots of ways to do this correctly. Incrementing it on render is not, since you're doing model work in UI code (broken conceptually and in implementation).
First, store the questions the user has visited somewhere. Why not a {questionsVisited:[]}
property on the user?
Use a Meteor.call(...)
method call to register a view instead:
Meteor.methods({
viewQuestion: function(questionId) {
// check if the user hasn't visited this question already
var user = Meteor.users.findOne({_id:this.userId,questionsVisited:{$ne:questionId}});
if (!user)
return false;
// otherwise, increment the question view count and add the question to the user's visited page
Meteor.users.update({_id:this.userId},{$addToSet:{questionsVisited:questionId}});
Questions.update({_id:questionId},{$inc:{views:1}});
return true;
});
So how about incrementing the view on UI changes? Well, let's not do that specifically. Let's increment the view count only when the question changes.
Meteor.autorun(function () {
var questionId = Session.get("question_id");
Meteor.call('viewQuestion',questionId,function(e,r) {
if (r)
console.log("Question " + questionId + " logged an increment.");
else
console.log("Question " + questionId + " has already been visited by user " + Meteor.userId();
});
});
And get rid of all this question helper stuff...
This is even better than what you originally wanted. Now views aren't counted twice for the same user. If that is the desired behavior, remove the questionsVisited
logic.
Only change the 'question_id'
session variable when you actually change the logical question the user is working with.
I solved this problem by using meteor-collection-hooks
First install it
>_ meteor add matb33:collection-hooks
Then in your model
Questions.after.findOne(function (userId, selector, options, doc){
Questions.update({_id: doc._id},{$inc:{views:1}});
});
And KABOOM Thats it
Rather than put in a helper, I would put this logic into the rendered event, ie.
Template.questionview.rendered ...
See the Meteor docs.
If you are using publish and subscribe ( you definitely should anyway) you can do it on your publish method like
Meteor.publish('posts', function(id) {
Posts.update({_id:id},{$inc:{view:1}});
return Posts.find({_id: id});
});
or on your subscribe callback
Meteor.subscribe("posts" , id {
onReady: function() { Meteor.call("incrementView", id);}});
this way you only increment the count once each time users open the browser.
来源:https://stackoverflow.com/questions/13776820/meteor-template-reload-infinity