According to the docs :
If you call Meteor.subscribe within a reactive computation, for example using Tracker.autorun, the subscription will automatically be cancelled when the computation is invalidated or stopped;
It is then explicitly mentioned that there is no need to stop subscriptions inside an autorun
.
Is this also the case for meteor helpers? I believe they count as reactive computation
, but I'm not entirely sure!
EDIT
Here is a snippet of code representing the situation.
The question then goes: Do I need to do something to stop the objectsSub
or is it all sorted automatically?
<template name ="Foo">
{{#with myContext}}
{{#each objects}}
<!--Show stuff-->
{{/each}}
{{/with}}
</template>
Template.Foo.onCreated(function(){
this.subscribe('myContextSub');
});
Template.foo.helpers({
myContext(){
return MyContextCollection.findOne();
},
objects(){
Meteor.Subscribe('objectsSub',this.someContextAttribute);
return ObjectsCollection.find({});
},
});
i'm not a fan of doing anything in helpers that has a side effect, such as going to the server. a helper can get called multiple times while the template is active, so imho it should really do nothing more than return a value.
in your case, at a minimum i would tie the subscription to the template, so the subscription goes away when the template is destroyed. e.g.
Template.foo.helpers({
objects() {
Template.instance().subscribe('objectsSub',this.someContextAttribute);
return ObjectsCollection.find({});
},
});
more likely, i would handle this "join" on the server side, when the master collection (myContextSub) is published. but that's only if the slave collection (objectsSub) is not expected to be reactive. (in the publish, you can set listeners on the added and changed events and add extra fields to the published objects, i.e. data from objectsSub).
if objectsSub is going to be reactive, then i would probably handle the subscription in onCreated() of the template. on the client, you would set an added listener on the master collection, then subscribe to the relevant slave collection as the items in the master collection are published. the helper could then simply do the find() as it does now. e.g.
Template.foo.onCreated(function() {
let self = this;
self.subscribe('myContextSub');
let cursor = MyContextCollection.find();
cursor.observe({
added: function(newDocument) {
// loop through the objects on newDocument, pulling out the context attributes to subscribe one or more times...
self.subscribe('objectsSub', someContextAttribute[s]);
},
changed: function(newDocument, oldDocument) {
// same as added
}
});
});
now the slave helper can be simpler:
Template.Foo.helpers({
myContext() {
return MyContextCollection.findOne();
},
objects() {
return ObjectsCollection.find({});
},
});
in this 2nd example, maybe the thing that's a little odd is i'm using a find() instead the findOne() you're using, in order to access the listeners that way. so perhaps you would need to check the way it's published or filter on the client.
if you wanted to stick with the findOne(), same concept applies: once the data is returned, you could examine it and subscribe to what you needed for the slave collection.