JavaScript: Why isn't this callback function not working? [duplicate] - javascript

This question already has an answer here:
Maximum call stack size exceeded on SetTimeout recursive function (Javascript) [duplicate]
(1 answer)
Closed 5 years ago.
It says: TypeError: myFunc is not a function
I want the output to be "I am happy, haha!".
I'm learning callback functions in JS.
function emotions(myString, myFunc) {
console.log("I am " + myString + ", " + myFunc(2));
}
var laugh = function(val) {
var ha="";
for(var i=0;i<val; i++) {
ha=ha+"ha";
}
return ha;
};
emotions("happy",laugh(2));

Try this:
emotions("happy", laugh);
You're having that issue because you're no passing the function itself, but it's result as the parameter. When you do laugh() you are running the function, not using it's reference, hence, you're passing it's result instead.
The call will the executed inside the emotions function as laugh(2), so that's the correct way.
function emotions(myString, myFunc) {
console.log("I am " + myString + ", " + myFunc(2));
}
var laugh = function(val) {
var ha="";
for(var i=0;i<val; i++) {
ha=ha+"ha";
}
return ha;
};
console.log(emotions("happy",laugh));

Related

Order of execution with setTimeout JS [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I'm trying to define a global variable value, from a function which is executed with the timeout method. The problem I'm facing here is can't get rid of the time interval.
*** Not Working (But I want the goal variable to be outside so that I can access it later).
function demo() {
var noOfGoals = 4;
goal = "He has scored " + noOfGoals + " in 45 Mins";
}
setTimeout(function() {
demo();
}, 2000);
console.log(goal);
****Working(but I dont want to access it from setTimeout)
function demo() {
var noOfGoals = 4;
goal = "He has scored " + noOfGoals + " in 45 Mins";
}
setTimeout(function() {
demo();
console.log(goal);
}, 2000);
Any new ideas or a better apporach than how have I done!
You can't get a return value from the function you pass to setTimeout.
For what you want to do, that would be written as:
function demo() {
var noOfGoals = 4;
return goal = "He has scored " + noOfGoals + " in 45 Mins";
}
function launch_goal () {
setTimeout(function() {
console.log(demo());
}, 2000);
}
launch_goal();
Or the other way to do it, you will need to use Promises

Setting global array from inside readFile [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 5 years ago.
I'm probably missing something simple here, but for some reason, when I set an array's value from inside a function, I can no longer read that array once outside of that function.
var threadArray = [];
function getThreads() {
var fs = require('fs');
// read list of threads
fs.readFile('./database/threadList.txt', function(err, data) {
var threadIds = data.toString().split("\n");
for(i in threadIds) { threadArray[i] = threadIds[i].split(","); }
console.log("This works: " + threadArray[0])
})
console.log("This does not work: " + threadArray[0] + " Returns [undefined]")
}
What am I missing here? I'm assuming something to do with the way I declared the array?
This is a timing issue. fs.readFile is an asynchronous operation - your second console.log that doesn't work is getting processed immediately after fs.readFile starts running and your threadArray is not yet populated. You can use fs.readFileSync instead
try {
var threads = fs.readFileSync('./database/threadList.txt');
var threadIds = threads.toString().split('\n');
for(i in threadIds) {
threadArray[i] = threadIds[i].split(",");
}
console.log("This works: " + threadArray[0]);
} catch (e) {
console.error("Error reading file: ", e);
}

Passing a parameter to a callback function [duplicate]

This question already has answers here:
JavaScript: Passing parameters to a callback function
(16 answers)
Closed 7 years ago.
I needed to pass a parameter to a callback function in Javascript, so I did the following which creates an anonymous function as a string and then passes it:
var f = "var r = function(result) {do_render(" + i + ",result.name,result.data);}"
eval(f)
$.getJSON("analysis?file=" + getParameterByName('file') + "&step=" + i,r);
This doesn't seem like a great idea however. Is there a better way?
There's several techniques that you can use to do this. One of which is to create a new function which "seals off" one of the variables:
function myCallback(i, result) { ... }
function createCurriedFunction(i, func, context) {
return function (result) { func.call(context, i, result); }
}
for (i = 0; i < 5; i += 1) {
var curriedFunc = createCurriedFuncion(i, myCallback, this);
$.getJSON(url, curriedFunc);
}
Context is the object for which the "this" will refer to in the callback function. This may or may not be needed for what you're doing; if not you can just pass in null.
There's actually a function that does exactly that called bind, and is used like
var curriedFunc = myCallback.bind(this, i), which will seal off the first variable.
It looks like you are having issues closing over i and to solve it used eval. Instead of that, simply close over it using an immediately invoked function expression (IIFE) like this:
(function(i){
//create a closure of the value of i
//so that it takes the immediate value of it instead of the end value
//based on the assumption i is from a loop iterator
$.getJSON("analysis?file=" + getParameterByName('file') + "&step=" + i,
function(result){
do_render(i, result.name, result.data);
}
);
})(i);//pass i into the IIFE in order to save its immediate value
You can simply do
var url = "myurl";
$.getJSON(url, function(result){
//callback function
});

Undefined return in $.get jquery [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
How to return AJAX response Text? [duplicate]
(2 answers)
Closed 9 years ago.
This question is already answered and voted. My edits are related to making it clearer and share some new knowledge acquired for other developers, I'm not expecting new answers.
I'm reading an XML with jQuery, but when I try to show an alert it's fully working; however, when I try to return the value it always gives me a message that it's undefined.
function getText(value){
var val;
var lang;
var location;
lang=getLanguage();
if (lang=='en')
lang='';
else
lang+='.';
location="resources/AppResources."+lang+'xml';
$.get(location, function (xml) {
$(xml).find("data").each(function () {
var name=$(this).attr('name');
if (name===value)
return $(this).find('value').text();
});
});
}
This is the code that calls it:
$(document).ready(function() {
alert(getText('AppTitle'));
});
If I add an alert in the return statement it shows me the value selected.
Small update:
As Arun P Johny explained in his answer, the missed part in my code was the callback that are defined by Mozilla in this way:
A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.
You can't return a value from a async method, the easiest solution is to use a callback function like this one:
function getText(value, callback) {
var val;
var lang;
var location;
lang = getLanguage();
if (lang == 'en')
lang = '';
else
lang += '.';
location = "resources/AppResources." + lang + 'xml';
$.get(location, function (xml) {
$(xml).find('data[name="' + value + '"]').each(function () {
callback($(this).find('value').text());
});
});
}
$(document).ready(function() {
getText('AppTitle', function(value){
alert(value);
})
});

Asynchronous (setTimeout) lambda doesn't use correct inputs [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Javascript setTimeout, Loops and Closure
(1 answer)
Closed 9 years ago.
I got the below code within a callback of xmlHTTPRequest callback function:
// some more code before
...
// schedule the UI update
var totSteps = 6;
for(var i = 0; i < listChangeEl.length; ++i) {
// callback pulse function
var curPulse = function cell_pulse(elName, curCnt) {
console.log("Accessing element: " + elName);
var curEl = document.getElementById(elName);
console.log("Element: " + elName + " = " + curEl);
var curColor = RGB2HTML(255, 255*(curCnt/totSteps), 255*(curCnt/totSteps));
if(curCnt < totSteps) {
// recursion here!
setTimeout( function(){ cell_pulse(elName, curCnt+1); }, 125);
}
};
// start it!
setTimeout( function() { (curPulse)(listChangeEl[i], 0); }, 125);
}
Apparently when the above is setTimeout( function() { (curPulse)(listChangeEl[i], 0); }, 125); is executed , listChangeEl[i] does contain the right id of a cell I want to update, but then, upon first execution of function cell_pulse the parameter elName is undefined.
What am I doing wrong? Does Javascript manage lambda (of lamdba) properly?
Thanks,
Ema

Categories

Resources