hallo all,
l have some problem with subscribing in meteor 1.1.0.2 i used package publish composite to publish it, but my application do resubscribing over and over again. it doesnt happen in previous versions. can you help me to solve this problem?
thanks
It would be easier for everyone if you provided some code.
okay this is my code…
models: function() {
var filter = {};
var limit = Session.get("limit") ? Session.get('limit') : null;
var name = Session.get("accountModalName") || "";
var cashOrBank = Router.current().accountType.cashOrBank ? Router.current().accountType.cashOrBank : null;
if (!limit)
Session.set("limit", 10);
if(name) {
filter = {
$and: [
{parentOrChild: "child"},
{accountTypeId: cashOrBank},
{
$or: [
{'code': {$regex: name, $options: "i"}},
{'name': {$regex: name, $options: "i"}}
]
},
]
};
}
filter['parentOrChild'] = "child";
if(cashOrBank)
filter['accountTypeId'] = cashOrBank;
if(limit) {
Meteor.subscribe("account", filter , {sort: {name: 1}, limit: limit});
var models = Account.find(filter , {sort: {name: 1}, limit: limit});
Session.set('models', models.fetch().length);
}
if(models) {
return {
getData: models,
};
}
},
It is not clear from this partial code in which javascript object your model: function(){}
belongs to, but I’m guessing it belongs to an iron router controller.
If that’s the case, limit
is a reactive dependency and iron router provides a reactive context in which routes run multiple times.
Therefore, you should put your subscription dependencies either within templates, or your routes onBeforeAction
or waitOn
or explicitly call .wait()
Otherwise, your subscriptions are going to keep tearing down and rerunning.
For better context, you should read through the examples at
Yes, you’re basically going against a few guidelines and thus your code is doing strange things. These guidelines could be stated as follows:
No side effects - no changing of state - in methods that provide models for views/templates. (And also no side effects in template/view code as well, but that one is much harder to violate since templates are not written in JS.)
In your case you are modifying Session
as well as calling Meteor.subscribe()
. One could say that the latter strictly speaking does not change state, but in the case of Meteor with its reactivity it does change part of the (client-side) state that leads to reevaluating various pieces of code and so you should avoid doing that in places that commonly expect side-effect free code.
And thinking about it, that’s actually the single guideline I can see you’re going against and that is causing crazy reevaluation of subscriptions.
So the solution would go something like this, like what @serkandurusoy also alluded to:
- move
Meteor.subscribe()
calls toiron:router
'swaitOn
orsubscriptions
methods - in your
models()
method just return the data you get from a regular client-sideAccount.find()
, with whatever sort/limit params you require. (Side-note: the collection should also be calledAccounts
, notAccount
, as per convention. If it’s a collection ofItem
, the collection itself is calledItems
.) -
Session.set()
should be called wherever it makes sense, but not in methods that also containMeteor.subscribe()
; usually that means it is done in places likeonBeforeAction()
(on Route/Controller) or event handling code.
That should get you most of the way to the solution for your “subscription thrashing” problem. If then you should still have trouble, ask more specific questions and check out some examples that contain solutions to similar features as yours (changable Collection.find() conditions with sort & limit), such as likely the Telescope code.
Fundamentally this is about proper architecture and fine-grained understanding of what-goes-where and current best-practices and subtle expectations that Meteor and libraries put on you and the code you write. Stuff like that comes with detail of understanding and exposure to problems like this one.
Oh and one more thing I forgot to mention:
Consider also if you truly to need to pass all of those parameters to the Meteor.subscribe()
call. Oftentimes it’s enough to subscribe to all or most of what the client is going to need and then do the filtering and pagination purely client-side. That way there’s less need to unsubscribe/resubscribe with different params and it’s harder to run into problems like this one. Not that it’s not worthwhile learning how to juggle these kinds of cases properly, but something to keep in mind and consider.