Skip to content

Instantly share code, notes, and snippets.

@vadym-vorobel
Last active September 3, 2018 12:53
Show Gist options
  • Save vadym-vorobel/3fa40f8122a219c52692c290efa58ffe to your computer and use it in GitHub Desktop.
Save vadym-vorobel/3fa40f8122a219c52692c290efa58ffe to your computer and use it in GitHub Desktop.
Manager that helps to work with Meteor subscriptions
import { Template } from 'meteor/templating';
import initSubsManager from './subs-manager';
const subsManager = initSubsManager();
// you can show subs manager logs with debug mode
// subsManager.debug();
Template.example.onCreated(function () {
subsManager.add(this.subscribe('subs.one'));
subsManager.add(this.subscribe('subs.two'));
});
Template.example.helpers({
subsReady() {
return subsManager.ready();
},
});
Template.example.onDestroyed(function () {
// you may stop subscription by it's name if you need
subsManager.stop('subs.one');
// or stop them all
subsManager.stop();
});
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import initSubsManager from '/imports/utility/subs-manager';
// your Mongo collection here
import Collection from '/imports/api/collection';
// your React component here
import ExampleComponent from './ExampleComponent';
const subsManager = getSubsManager();
export default withTracker(({ arg1, arg2 }) => {
const subsHandler = Meteor.subscribe('subs.one', { arg1, arg2 });
subsManager.add(subsHandler);
const data = Collection.find().fetch();
return {
data,
loading: !subsHandler.ready(),
// need to bind
onComponentUnmount: subsManager.stop.bind(subsManager),
};
})(ExampleComponent);
/* eslint-disable no-console, no-underscore-dangle */
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
const getMeteorSubscriptions = () => Meteor.default_connection._subscriptions;
const getMockSubscription = subscriptionId => ({
_id: subscriptionId,
name: 'Unnamed subscription',
ready: true,
stop: () => true,
newSubscription: true,
});
const getSubscriptionById = ({ subscriptionId }) => {
const subscriptions = getMeteorSubscriptions();
return subscriptions[subscriptionId] || getMockSubscription(subscriptionId);
};
const getSubscriptionByName = (subscriptionName) => {
const subscriptions = getMeteorSubscriptions();
const subscription = Object.values(subscriptions).find(({ name }) => name === subscriptionName);
return subscription || getMockSubscription(null);
};
export default () => {
// provide reactivity to the subs manager
const dep = new Tracker.Dependency();
return {
_debugMode: false,
subscriptions: [],
add(subscription) {
// check whether the subscription already exists
const subsExists = this._checkSubscriptionExists(subscription);
// don't add existing subs one more time
if (!subsExists) {
const subsInfo = getSubscriptionById(subscription);
this._log(`Added subscription "${subsInfo.name}" (${subsInfo.id})`);
this.subscriptions = this.subscriptions.concat(subscription);
}
dep.changed();
},
ready() {
dep.depend();
// ready if there are no subscriptions
if (this.subscriptions.length === 0) {
return true;
}
if (!this._debugMode) {
return this.subscriptions.every(subscription => subscription.ready);
}
const allSubsReady = this.subscriptions.every((subscription) => {
const { ready: isSubsReady } = subscription;
const subsInfo = getSubscriptionById(subscription);
// eslint-disable-next-line
this._log(
`Subscription "${subsInfo.name}" (${subsInfo.id}): ${isSubsReady ? 'READY' : 'NOT READY'}`
);
return isSubsReady;
});
this._log(allSubsReady ? 'All subs are ready' : 'Not all subs are ready');
return allSubsReady;
},
stop(subscriptionName) {
if (subscriptionName) {
const subscriptionToStop = getSubscriptionByName(subscriptionName);
this._log(`Stopping subscription ${subscriptionName} (${subscriptionToStop.id})`);
subscriptionToStop.stop();
this.subscriptions.filter(({ subscriptionId }) => subscriptionId !== subscriptionToStop.id);
this._log(`Subscription ${subscriptionName} stopped`);
} else {
this._log('Stopping subscriptions');
this.subscriptions.forEach(subscription => subscription.stop());
this.subscriptions = [];
this._log('All subscriptions stopped');
}
dep.changed();
},
debug() {
this._debugMode = true;
},
_log(message) {
if (this._debugMode) {
console.log(`[SubsManager]: ${message}`);
}
},
_checkSubscriptionExists({ subscriptionId }) {
return this.subscriptions.findIndex(({ subscriptionId: id }) => subscriptionId === id) > -1;
},
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment