Using Meteor: strange behavior using helper functions in template helpers - javascript

I'm getting some strange behavior using Meteor.
I'm in a template helper defined in client/ . The function "percentCompleted" is a helper function defined in client/lib/helper.js. When I call "percentCompleted" in the return line, percentCompleted completes normally. However, whenever I call percentCompleted outside of the return line, the console logs an error that the function "percentCompleted" is undefined. Why would a helper function be defined or undefined depending on where in the template helper it is called??
This works:
Template.chapter.percentComplete = function(){
if(_.isEmpty(this))
return "";
return percentCompleted(this)
}
This throws an error with "percentCompleted" undefined.
Template.chapter.percentComplete = function(){
if(_.isEmpty(this))
return "";
var percentCompleted = percentCompleted(this)
return percentCompleted;
}

The problem is that you have a local variable called percentCompleted which shadows the function percentCompleted. Rename the variable to something else and it should work.
Note that local variable declarations in Javascript are hoisted to the top of the function, so it behaves as if you wrote:
Template.chapter.percentComplete = function(){
var percentCompleted;
if(_.isEmpty(this))
return "";
// Here we attempt to call the function in the percentCompleted
// var, but that is undefined.
percentCompleted = percentCompleted(this)
return percentCompleted;
}

Related

Method not defined as a function (while defined as one)

I am experimenting a strange issue: at the beginning of my code, I defined a function like so:
function rootEmbed()
{
var embed = new Discord.RichEmbed()
.setColor(config.embedColor);
return embed;
//returns an object
}
Later in the same file, I define another function which calls the one above, like so:
function commandList()
{
var embed = rootEmbed();
//....
}
Calling that function causes no problem, however calling the following function returns an error that says
(node:4988) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: rootEmbed is not a function
Here is the told function:
function voidTrader(trader)
{
var rootEmbed = rootEmbed();
//...
}
I can't figure out why does the voidTrader() method causes an error while commandList() turns out perfectly fine. What am I doing wrong?
If you want the full code, you can find it here.
Thanks in advance!
This is a combination of variable hoisting and variable shadowing. When you initialize a variable var x = 5, what happens is that var x is hoisted to the top of the code file. However, function declarations are hoisted even higher. Meaning that when your file is run, this is what is happening:
function rootEmbed (){//...code here}
var rootEmbed = undefined;
To fix this problem, change this:
function voidTrader(trader)
{
var rootEmbed = rootEmbed();
//...
}
To something like this:
function voidTrader(trader)
{
var rootEmbedResult = rootEmbed();
//...
}
There is another problem at lines 25-26:
var year = "" + stamp.getYear();
var year = twoDigits("20" + year.substr(-2));
year is declared with var twice.

What does "Functions can only be declared at the top level of a scope" mean? [duplicate]

I have this error when using FireFox with strict mode. But am unsure what it means. I assumed it meant that the function had to be declared before it was called upon but the error still occurs.
SyntaxError: in strict mode code, functions may be declared only at top level or immediately within another function
This is my snippet of code where it is causing the error:
var process = new function(){
var self = this;
self.test = function(value,callback){
var startTime = Date.now();
function update(){ //<--- error is here
value++;
startTime = Date.now();
if(value < 100){
setTimeout(update, 0);
}
callback(value);
}
update();
}
};
So i'm wondering how would I write this snippet of code out correctly with strict ? What does it mean by top level ? Does that mean globally defined and not locally within a function ?
Also given I have use strict why does this problem not occur in Chrome?
You must put local functions BEFORE other code within the parent function in strict mode:
var process = function () {
var self = this;
self.test = function (value, callback) {
function update() {
value++;
startTime = Date.now();
if (value < 100) {
setTimeout(update, 0);
}
callback(value);
}
var startTime = Date.now();
update();
}
};
This is described in this articles:
New ES5 strict mode requirement: function statements not at top level of a program or function are prohibited
MDN Strict Mode
In my own testing though (and counter to the articles I've read), I find that current versions of both Chrome and Firefox only complain about a local function definition if it is inside a block (like inside an if or for statement or a similar block.
I guess I need to go find an actual spec to see what is says.
The Internet explorer error explicitly states functions names cannot be "declared" within a function. So using a self-invoking function expression has worked for me.
This code fails:
c.prototype.isitReal=function(t){
var matched = false;
this.each(function(item){
// declaring a new function within a function fails
function getChildren(el){
....
getChildren(el[a].children);
....
}
getChildren(el.children); // invoke function
});
return matched;
};
This code works:
c.prototype.isitReal=function(t){
var matched = false;
this.each(function(item){
// convert the function to an expression of a function
// by wraping the entire function in ( )
(function getChildren(el){
....
getChildren(el[a].children);
....
// then invoke the function expresion by adding ()
// to the end. Pass in any arguments here also
})(el.children,arg2,arg3);
});
return matched;
};
Tested in FF 76, MSIE 10, Chrome Canary 81

Bind Mocking Function inside function

I am writing QUnit test case for my application . Basically I have three Files
like below . DataServices.js has getObjectDetails method which does ajax call
to get data and passes result in callback .
Resolver.js loads DataServices.js using require.
I am writing test case for Proxy.resolve method , in which i want to avoid actual api call , to do this I created mock object of DataServices in Test.js and call Resolver proxy resolve method .
I tried using bind , But still points to actual method of DataServices.js not what I bind in Test.js
DataServices.js
define(["module"], function(module) {
"use strict";
var Details = {
getObjectDetails :function(param,callback){
//API AJAX CALL
// Callback once done
}
};
return {Details : Details }
});
Resolver.js
define(["DataServices"],function(DataServices){
var Proxy= {
resolve : function(){
var Details = DataServices.Details ;
Details.getObjectDetails("xyz", function(result){
// Do Operation After Result
});
}
};
return {Proxy:Proxy}
});
Test.js
define(["Resolver.js" ],function(Resolver){
var DataServices= {
Details : {
getObjectDetails : function(undefined,onSuccess, onError) {
return onSuccess({"X":"Y"});
}
}
};
Resolver.Proxy.resolve.bind(DataServices);
Resolver.Proxy.resolve(); // This is still calling DataServices.js Details
// Not the above muck object
});
In simple program , I want to call mock z function , not z which is inside x .
How to achieve this.
var x = {
z:function(b){
console.log("Z Actual Function..."+b);
},
a : function(){
this.z(3);
}
};
var z = function(b){
console.log("Mock ..."+b)
}
x.a.bind(z);
x.a();
//Z Actual Function...3
But I want Mock ...3 to print
First problem
Using .bind creates a new function, it doesn't change the value of this in the original function.
To use bind in your case you would do something like this instead:
var mockedA = x.a.bind(z);
mockedA();
If you want to call the function immediately without assigning it to a variable you can use .call or .apply instead.
eg:
x.a.call(z); // runs `a()` immediately with `this` set to `z`
The second problem
By binding x.a to z you're changing the value of this to the value provided (the mock z function). So inside x.a when you call this.z(3) you're effectively trying to call z.z(3), which is a non existent function and so will throw a TypeError.
There are probably better ways of doing it but this is a way that answers your question:
var x = {
z:function(b){
console.log("Z Actual Function..."+b);
},
a : function(){
this.z(3);
}
};
var mock = {};
mock.z = function(b){
console.log("Mock ..."+b)
}
// with bind
var mockXA = x.a.bind(mock);
mockXA();
// with call
//x.a.call(mock)

JavaScript - Get object / call function inside function's return statement

I have a weird situation, I'm working with a 3rd party API and I can use JavaScript but all my code has to be a return function in order for it to work, here is how my app looks like, it gets plugged into their system:
app.js
(function() {
var myVar1 = null;
var globalFunction = function(){
alert('TEST');
}
return {
test: null,
requests: {
},
events: {
'app.activated': 'initApp'
},
insideFunction: function(item){
//some code
},
initApp:function(){
//some code
//I can set the gobal variables using varName = Value
//I can set the return variables using this.varName = Value
//I can call the return functions using this.insideFunction()
//the entire app is basically run from inside 'return'
}
};
}());
I can access the global vars / function from inside the return, but how can I do it vice-versa? I need to call insideFunction from the globalFunction.
Assign the object you're returning to a variable before returning it.
var api = {
test: null,
...
};
var globalFunction = function() {
api.insideFunction();
};
return api;

How to update global object

Iam trying to run an external function inside nightmarejs evalute function...As you can see my code below...
function get_my_links(url){
vo(function* () {
var nightmare = Nightmare();
var href_link = []; // i have tried making it as global without var but did not work
var title = yield nightmare
.goto('https://examply/'+url)
.evaluate(function (href_link,url,get_my_links) {
$('.myclass').each(function() {
href_link.push($(this).attr("href"));
});
if($.isNumeric($("#someid").val()))
{
get_my_links(1)
}
else{
return href_link;
}
},href_link,url);
console.log(title);
yield nightmare.end();
})(function (err, result) {
if (err) return console.log(err);
});
}
get_my_links(0)
By above code I am trying to update href_link ...
1) How to make it Global object,so that everytime the function is called new value should be added with the existing values?
1st The reason
// i have tried making it as global without var but did not work
is not working because though you making the object global but every time you call get_my_links function, it will update the global object to empty array.
For your use case, define href_link before defining get_my_links function. Like
var href_link =[];
function get_my_links() {
...
}
Defining href_link after function definition like ->
function get_my_links() {
...
}
var href_link =[];
will throw an error of undefined value of href_link inside get_my_links function due to hoisting which must be the case you have mentioned in above comment.
electron uses node.js, so you can use the global object of node.js to store the value.
https://nodejs.org/api/globals.html#globals_global
When you use this solution you should be able to access the value also from other parts of your app.

Categories

Resources