Reactive variable is undefined when it is defined - javascript

I would like to get some help debugging a situation where a Reactive Variable is undefined, when it has been defined already.
This code is attaching a Reactive Variable to the template instance, and using the variable in template.autorun().
Template.home.onCreated(function () {
this.limit = new ReactiveVar(15);
this.autorun(function () {
this.subscribe('recent-topics', this.limit.get());
});
});
When I load the template for the first time, I expect the template to subscribe to recent-topics with an argument 15. However, the code throws an error:
Uncaught TypeError: Cannot read property 'get' of undefined
Any ideas why?

Just an answer for the sake of spreading the joys of ES6:
Template.home.onCreated(function () {
this.limit = new ReactiveVar(15);
this.autorun(() => {
this.subscribe('recent-topics', this.limit.get());
});
});
Make sure you add the grigio:babel package, and your Javascript file ends in .es6.js, .es6, or .jsx.
Explanation
In ES6 (aka ECMAScript 6), there's a new "fat arrow" syntax which is very similar to CoffeeScript's implementation. In ES6, when you do something like this:
someFunc = function () {
anotherThing((var1, var2) => {
this.thing = true;
});
};
It's the same as doing this:
someFunc = function () {
var self = this;
anotherThing(function (var1, var2) {
self.thing = true;
});
};

This is a scoping issue.
Inside of your Tracker.autorun, this no longer refers to the template, but the autorun's callback function. Inside of the autorun, try calling Template.instance().limit.get().

Better than using Template.instance().limit.get() (ryan's answer)
You should do something like this:
Template.home.onCreated(function () {
var self = this;
self.limit = new ReactiveVar(15);
self.autorun(function () {
self.subscribe('recent-topics', self.limit.get());
});
});

Related

Function chaining with function names from list [duplicate]

What is the equivalent code of window["functionName"](arguments) in NodeJS server-side?
If you need such a capability within a module, one hack is to store such module functions in variables within the module and then call them by accessing them from the module object properties. Example:
var x = { }; // better would be to have module create an object
x.f1 = function()
{
console.log('Call me as a string!');
}
Now, within the module, you can call it using the value from a string:
var funcstr = "f1";
x[funcstr]();
I am learning the ropes with Node myself, the above is probably all sorts of wrong :-). Perhaps a marginally better way to write this example would be (for the module m.js):
module.exports =
{
f1: function() { console.log("Call me from a string!"); },
f2: function(str1) { this[str1](); }
}
Now you can:
var m = require('m.js');
m.f2('f1');
Or even just:
var m = require('m.js');
m['f1']();
FWIW!
you're looking for global
Note, however, that in modules nothing is ever exposed to this level
1) If methods are in same js file
define all methods as properties of Handler:
var Handler={};
Handler.application_run = function (name) {
console.log(name)
}
Now call it like this
var somefunc = "application_run";
Handler[somefunc]('jerry codes');
Output: jerry codes
2) If you want to keep methods in a different js file
// Handler.js
module.exports={
application_run: function (name) {
console.log(name)
}
}
Use method defined in Handler.js in different.js:
// different.js
var methods = require('./Handler.js') // path to Handler.js
methods['application_run']('jerry codes')
Output: jerry codes
If you want to call a class level function using this then following is the solution and it worked for me
class Hello {
sayHello(name) {
console.log("Hello " + name)
}
callVariableMethod() {
let method_name = 'sayHello'
this[`${method_name}`]("Zeal Nagar!")
}
}
If You need it in module scope, You can use something like this
var module = require('moduleName');
module['functionName'](arguments);
Honestly, looking at all these answers they seem a bit too much work. I was playing around to look for other ways around this. You can use the eval() command to print a variable as text then call it as a function
I.e
let commands = ['add', 'remove', 'test'];
for (i in commands) {
if (commands[i] == command) {
var c = "proxy_"+command;
eval(c)(proxy);
}
}
eval(string)(arg1, arg2);
This example script would execute the function proxy_test(proxy)
You know, the OP's code inspired me to try this:
global.test = function(inVal){
console.log(inVal);
}
global['test']('3 is the value')
But now that I think about it, it's no better than #Ravi' s answer.
I use this for node, see if this approach works for you
var _ = require('lodash');
var fnA1 = require('functions/fnA1');
var fnA2 = require('functions/fnA2');
module.exports = {
run: function(fnName, options, callback) {
'use strict';
var nameSpace = fnName.toString().split('.');
// if function name contains namespace, resolve that first before calling
if (nameSpace.length > 1) {
var resolvedFnName = this;
_.forEach(nameSpace, function(name){
resolvedFnName = resolvedFnName[name];
});
resolvedFnName(options, callback);
} else {
this[fnName](options, callback);
}
},
fnA1: fnA1,
fnA2: fnA2
};
call this like
importVariable.run('fnA1.subfunction', data, function(err, result){
if (err) {return callback(err);}
return callback(null, result);
});
That is not specific to the window object. In JavaScript any property of the object can be accessed this way. For example,
var test = {
prop1 : true
};
console.log(test.prop1); // true
console.log(test["prop1"]); // also true
Read more here : https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects

using a DOM event callback inside an object

In p5.js, How do you make a DOM element callback a function if both the DOM element and the function are inside the same object ? for example :
function Snape()
{
this.myInput = createInput("");
this.myInput.changed(this.erase);
this.erase = function()
{
}
}
when I type something in this.myInput, I would like it to call the function this.erase, but I get the error 11913: Uncaught TypeError: Cannot read property 'bind' of undefined
is it possible ?
——————————————————————————————————————————
EDIT : The main issue is solved if I declare this.erase before I call it :
function Snape()
{
this.myInput = createInput("");
this.erase = function()
{
}
this.myInput.changed(this.erase);
}
but that’s a really messy way to do it.
Moreover, I wasn’t able to implement what was suggested in the answer :
In p5.js, the way we invoke a callback is like this :
this.myInput.changed(this.erase);
if I do this
this.myInput.changed(this.erase());
I get this error : Uncaught TypeError: undefined is not a function
So, when I try to call this.erase using this (as was suggested) :
this.myInput.changed(function(){ myself.erase(); });
I get the same error Uncaught TypeError: undefined is not a function
I tried all the different possibilities :
this.myInput.changed(function(){ myself.erase() });
this.myInput.changed(function(){ myself.erase; });
this.myInput.changed(function(){ myself.erase });
neither of those are working.
I can’t use the => function because I need to call this.erase a lot of times in different instance of the object, and from multiple DOM elements.
You have to save this into a variable so you can then reference it:
function Snape() {
var myself = this;
this.myInput = createInput("");
this.myInput.changed(function(){ myself.erase(); });
this.erase = function()
{
console.log("erased");
}
}
Another (less elegant) solution would be this:
var input;
function setup () {
createCanvas(500, 300);
input = new Snape () ;
}
function Snape () {
this.myInput = createInput("");
this.myInput.changed(tunnel);
this.erase = function()
{
console.log("erased");
}
}
function tunnel () {
input.erase();
}

Mocking ngResource in Angular unit tests

I have an ngResourceMockFactory which looks like this:
(function() {
'use strict';
angular.module('app')
.factory('NgResourceMock', ngResourceMockFactory)
;
ngResourceMockFactory.$inject = [];
function ngResourceMockFactory() {
function NgResourceMock() {
var context = this;
context.$promise.then = function() {
context.prototype.$promise.then.apply(context, arguments);
};
context.$promise.finally = function() {
context.prototype.$promise.finally.apply(context, arguments);
};
}
NgResourceMock.prototype.$promise = {
then: function(onSuccess, onError) {
this.$promise.onSuccess = onSuccess;
this.$promise.onError = onError;
},
finally: function(onComplete) {
this.$promise.onComplete = onComplete;
}
};
return NgResourceMock;
}
})();
I inject this into my tests in a beforeEach like so:
beforeEach(inject(function(NgResourceMock) {
ngResourceMock = new NgResourceMock();
}));
then I use it like this:
describe('initiateWorkflow function', function() {
beforeEach(function() {
vm.player = {id: 123};
spyOn(dataService, 'initiateWorkflow').and.returnValue(ngResourceMock);
vm.initiateWorkflow();
});
it('should call dataService.initiateWorkflow', function() {
expect(dataService.initiateWorkflow).toHaveBeenCalledWith({playerId: vm.player.id}, {});
});
});
but I keep seeing the following error:
TypeError: 'undefined' is not an object (evaluating 'context.prototype.$promise')
This leads me to believe that something is wrong with my ngResourceMockFactory, but I'm not sure what it is.
Don't know if this can be of any help, but if you are trying to evaluate asynchronous operations in your tests, you may want to use the done() method in Jasmine.
As per their documentation:
beforeEach(function(done) {
setTimeout(function() {
value = 0;
done();
}, 1);
});
by passing done as a parameter of the beforeEach callback, any test run after the before each will wait until the done() function has been called.
Source: Jasmine (Asynchronous Support section).
Hope this helps.
Here is the solution to your problem.
The error TypeError: 'undefined' is not an object (evaluating 'context.prototype.$promise') is caused when you try to invoke the promise object before invoking the function into which it is defined or into which your parent function is defined.
Here the returnValue(ngResourceMock) is directly calling into the function without the context and parameters need to be defined.
Therefore you can try to add another beforeEach statement like
beforeEach(angular.mock.module(app));
to load your app module
Here may be the same concept related to your problem another link here.
Hope it may help you a bit.

how to override a returned nested method in javascript?

Say I'm using a library with the code that looks like below:
(function($)
{
function Library(el, options)
{
return new Library.prototype.init(el, options);
}
Library.fn = $.Library.prototype = {
init: function(el, options) {
this.$elm.on('keydown.library', $.proxy(this.keydown.init, this));
}
keydown: function() {
return {
init: function(e) {
... somecode
},
checkStuff: function(arg1, arg2) {
...someCode
}
}
};
}
})(jQuery);
It has a plugin system that provides access to this where this is an Object {init: function, keydown: function...}. I want to override the keydown.init function. Normally I could see using something like _.wrap to do it:
somefunc = _.wrap(somefuc, function(oldfunc, args) {
donewstuff();
oldfunc.call(this.args);
});
but that doesn't seem to work on the returned nested method e.g.:
this.keydown.init = _.wrap(this.keydown.init, function(oldfunc, args) {
donewstuff();
oldfunc.call(this.args);
});
The question might be answered on here but I don't really know the right words to use to describe this style of coding so its hard to search. Bonus points if you let me know if it is even correct to call it a nested returned method?
This pattern is called a module. The best thing you can do here is cache the method you want to override and call the cached method inside your override:
somefunc._init = somefunc.init;
somefunc.init = function () {
doStuff();
this._init();
};
I checked _.wrap and it does the same thing, what your missing as pointed out by another answer is you're losing the context of somefunc. In order to prevent that you can do:
somefunc.init = _.wrap(_.bind(somefunc.init, somefunc), function (oldRef, args) {
doStuff();
oldRef.call(this.args);
});
You will need to decorate (read: wrap) the keydown function so that you can wrap the init method of the object it returns:
somefunc.keydown = _.wrap(somefunc.keydown, function(orig) {
var module = orig(); // it doesn't seem to take arguments or rely on `this` context
module.init = _.wrap(module.init, function(orig, e) {
donewstuff();
return orig.call(this, e);
});
return module;
});
The problem is that your method is run out of context.
You need to set its this context (use .bind() for this)
somefunc.init = _.wrap(somefuc.init.bind(somefunc), function(oldfunc, args) {
donewstuff();
oldfunc.call(this.args);
});

Equivalent of "window["functionName"](arguments)" in server-side

What is the equivalent code of window["functionName"](arguments) in NodeJS server-side?
If you need such a capability within a module, one hack is to store such module functions in variables within the module and then call them by accessing them from the module object properties. Example:
var x = { }; // better would be to have module create an object
x.f1 = function()
{
console.log('Call me as a string!');
}
Now, within the module, you can call it using the value from a string:
var funcstr = "f1";
x[funcstr]();
I am learning the ropes with Node myself, the above is probably all sorts of wrong :-). Perhaps a marginally better way to write this example would be (for the module m.js):
module.exports =
{
f1: function() { console.log("Call me from a string!"); },
f2: function(str1) { this[str1](); }
}
Now you can:
var m = require('m.js');
m.f2('f1');
Or even just:
var m = require('m.js');
m['f1']();
FWIW!
you're looking for global
Note, however, that in modules nothing is ever exposed to this level
1) If methods are in same js file
define all methods as properties of Handler:
var Handler={};
Handler.application_run = function (name) {
console.log(name)
}
Now call it like this
var somefunc = "application_run";
Handler[somefunc]('jerry codes');
Output: jerry codes
2) If you want to keep methods in a different js file
// Handler.js
module.exports={
application_run: function (name) {
console.log(name)
}
}
Use method defined in Handler.js in different.js:
// different.js
var methods = require('./Handler.js') // path to Handler.js
methods['application_run']('jerry codes')
Output: jerry codes
If you want to call a class level function using this then following is the solution and it worked for me
class Hello {
sayHello(name) {
console.log("Hello " + name)
}
callVariableMethod() {
let method_name = 'sayHello'
this[`${method_name}`]("Zeal Nagar!")
}
}
If You need it in module scope, You can use something like this
var module = require('moduleName');
module['functionName'](arguments);
Honestly, looking at all these answers they seem a bit too much work. I was playing around to look for other ways around this. You can use the eval() command to print a variable as text then call it as a function
I.e
let commands = ['add', 'remove', 'test'];
for (i in commands) {
if (commands[i] == command) {
var c = "proxy_"+command;
eval(c)(proxy);
}
}
eval(string)(arg1, arg2);
This example script would execute the function proxy_test(proxy)
You know, the OP's code inspired me to try this:
global.test = function(inVal){
console.log(inVal);
}
global['test']('3 is the value')
But now that I think about it, it's no better than #Ravi' s answer.
I use this for node, see if this approach works for you
var _ = require('lodash');
var fnA1 = require('functions/fnA1');
var fnA2 = require('functions/fnA2');
module.exports = {
run: function(fnName, options, callback) {
'use strict';
var nameSpace = fnName.toString().split('.');
// if function name contains namespace, resolve that first before calling
if (nameSpace.length > 1) {
var resolvedFnName = this;
_.forEach(nameSpace, function(name){
resolvedFnName = resolvedFnName[name];
});
resolvedFnName(options, callback);
} else {
this[fnName](options, callback);
}
},
fnA1: fnA1,
fnA2: fnA2
};
call this like
importVariable.run('fnA1.subfunction', data, function(err, result){
if (err) {return callback(err);}
return callback(null, result);
});
That is not specific to the window object. In JavaScript any property of the object can be accessed this way. For example,
var test = {
prop1 : true
};
console.log(test.prop1); // true
console.log(test["prop1"]); // also true
Read more here : https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects

Categories