Skip to content

Instantly share code, notes, and snippets.

@zetekla
Created September 21, 2017 04:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zetekla/e76198d4a4c80b1c815835cb360ca09a to your computer and use it in GitHub Desktop.
Save zetekla/e76198d4a4c80b1c815835cb360ca09a to your computer and use it in GitHub Desktop.
Meteor Tracker guard
// Only trigger enclosing computation if the return value of
// f is not EJSON.equals to the previuous return value
Tracker.guard = function(f) {
if (Meteor.isServer || !Tracker.currentComputation) {
return f();
}
let dep = new Tracker.Dependency(),
curView = Blaze.currentView,
tplFunc = Template._currentTemplateInstanceFunc;
dep.depend();
let value, newValue;
Tracker.autorun(comp => {
if (curView) {
newValue = Blaze._withCurrentView(curView, () => {
return tplFunc ? Template._withTemplateInstanceFunc(tplFunc, f) : f();
});
}
else {
newValue = f();
}
if (!comp.firstRun && !EJSON.equals(newValue, value)) {
dep.changed();
}
value = EJSON.clone(newValue);
});
return newValue;
};
// Return a function which will always return the same
// value as f and changes value whenever f changes value,
// but is more efficient because it caches the value of f
// in a reactive variable.
Tracker.memo = function(f) {
if (Meteor.isServer)
return f;
let value = new ReactiveVar(undefined, EJSON.equals),
tracker = Tracker.nonreactive(() => Template.instance()) || Tracker,
firstRun = true,
comp = tracker.autorun(() => {
if (!firstRun)
value.set(f());
});
return () => {
if (firstRun) {
firstRun = false;
comp._compute();
}
return value.get();
};
};
// Starting work on tracking who triggered an autorun
let originalCompute = Tracker.Computation.prototype._compute;
Tracker.Computation.prototype._compute = function() {
originalCompute.call(this);
this.callers = [];
};
let originalInvalidate = Tracker.Computation.prototype.invalidate;
Tracker.Computation.prototype.invalidate = function() {
if (!this._callers)
this._callers = [];
let e = new Error('dummy');
let stack = e.stack.replace(/^[^\(]+?[\n$]/gm, '')
.replace(/^\s+at\s+/gm, '')
.replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@')
.split('\n');
this._callers.push(stack);
originalInvalidate.call(this);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment