scope of javascript callback functions [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I was wondering what is the scope of a passed in callback function in Javascript.
callback = function() {
alert('hello');
}
func1 = function() {
func2(callback);
}
func2 = function(callback) {
func3(callback);
}
func3 = function(callback) {
callback();
}
When I call func1() .. it seems as if this extra layer of function loses that reference to callback(). I can call callback() from within func2, but not func3. Can anyone please advise?

you should see your code written as
var callback;
var func1;
var func2;
var func3;
callback = function() {
alert('hello');
}
func1 = function() {
func2(callback);
}
func2 = function(callback) {
func3(callback);
}
func3 = function(callback) {
callback();
}
the func1 scope includes all variables callback, func2 and func3. since all functions are initialized using function expressions and not function declarations like
function callback() {alert('hello');}
calling func1 will alert hello only if it is called at the bottom of your snippet.

Hopefully I have explained some of this in this jsFiddle. Look over the comments in the JS. This was done in a hurry, so feel free to update/comment/question. Code is below if you'd like to put test it locally.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="test">
</div>
<script>
// We're going to name our /callback/ something else to help with
// the confusion of using /callback/ wording everywhere.
var showMessage = function(message) {
document.getElementById("test").innerHTML= message;
}
var tellMe = function(message) {
document.getElementById("test").innerHTML = message;
return "Oh yes we did!";
}
// here we'll have one called callback just to show the name callback isn't anything special
var callback = function(message) {
document.getElementById("test").innerHTML= message;
}
// doesn't show anything, because you're not passing in a call back.
// if we wanted this to work we would have a param called callbackTest and
// we's pass in a function to be called back.
func1 = function() {
func2(callbackTest("Hi from func1"));
}
// does show message because you're not calling a callback, you're calling a function directly. Which is what you were doing above, just that there happened to not be a function called callback
// see explination below why we don't see Hi from func2, but Hi from func1_5 instead
func1_5 = function() {
func2(callback("Hi from func1_5"));
}
// here we're actually accepting a callback function named showMessage and using that as our callback by assigning it to the callback parameter variable. (remember, callback is not a fancy statement or call or anything. It's just a commonly named variable for.... callbacks ;) )
func2 = function(callback) {
// what you're doing here is actually passing the result of calling the callback (showMessage) to func3, and not the function. So you're actually executing the callback (showMessage) with the "Hi from func2", which outputs that, but returns nothing. So you're not passing anything at all to func3.
func3(callback("Hi from func2"));
}
// so here we'll show the previous problem, but working to provide insight.
// we're passing in a different /callback/ called tellMe. This function actually returns a string.
func2_5 = function(callback) {
func3(callback("Hi from func2_5"));
}
// here you're actually passing in a function to this as a callback, which is actually the showMessage function we pass in below.
func3 = function(callback) {
// the thing is, the callback variable is now a string and not a function because we got the result of the passed in callback call from above.
// so this will show a string for callback ("Oh yes we did!")
document.getElementById("test").innerHTML = callback;
// and this won't show anything because callback is not a function in this scope
if (typeof(callback) !== "function") {
alert("callback isn't a function");
}else {
callback(("Hi from func3"));
}
}
func4 = function() {
if (typeof(callback) === "undefined" ) {
alert ("the callback variable was never defined")
} else {
callback(("Hi from func4"));
}
}
</script>
<button onclick="func1();">func1</button>
<button onclick="func1_5()">func1_5</button>
<button onclick="func2(showMessage);">func2</button>
<button onclick="func2_5(tellMe);">func2_5</button>
<button onclick="func3();">func3</button>
<button onclick="func4()">func4</button>
</body>
</html>

Related

parameter of a function used in turn as parameter of setTimeout function in javascript [duplicate]

This question already has answers here:
How can I pass a parameter to a setTimeout() callback?
(29 answers)
Closed 12 months ago.
function f1()
{
c = setTimeout(f2,200);
}
function f2()
{
//code
}
The above code is just fine. But what I want to ask that: can I use some argument in function f2() which is passed from the calling environment? That is:
function f1(v1)
{
c = setTimeout(f2(v1),200);
}
function f2(v2)
{
//code
}
Is it valid? Because I tried something like this,but the problem is that I am not able to clearTimeout by using variable c. I am not sure what to do.
Use Closure -
function f1(v1)
{
c = setTimeout(f2(v1), 200);
}
function f2(v2)
{
return function () {
// use v2 here, and put the rest of your
// callback code here.
}
}
This way you will be able to pass as many arguments as you want.
Since you are declaring c as a global variable (which is bad), you can easily clear the timeout using -
clearTimeout(c);
If you are still not being able to clear the timeout, it only means that the duration has elapsed and your callback fired, or there is some error somewhere else. In that case, post your code that you are using to clear your timeout.
You can either use the function.bind method or you can simply wrap the invocation
function f1(v1) {
c = setTimeout(function() {
f2(v1);
}, 200);
}
var timeout;
// Call `f2` with all arguments that was passed to the `f1`
function f1 () {
var args = arguments;
timeout = setTimeout(function () { f2.apply(this, args) }, 200);
}
Or in this way:
// Call `f2` with some params from `f1`
function f1 (v1) {
timeout = setTimeout(function () { f2(v1) }, 200);
}
Answer to your question: you couldn't clear the timeout because you execute function immediately.

Javascript callback function with parameters [duplicate]

This question already has answers here:
Pass an extra argument to a callback function
(5 answers)
Closed 6 years ago.
This question looks like a duplicate, as the title is nearly replicated. But, my issue seems simpler and I can't find the answer to it.
I have a Javascript function that executes another callback function, it works like this:
<script type='text/javascript'>
firstfunction(callbackfunction);
</script>
where callback function is defined as:
callbackfunction(response) {
if (response=='loggedin'){
// ... do stuff
}}
but I want it to be something like this:
callbackfunction(response, param) {
if (response=='loggedin'){
// ... do stuff with param
}}
My question is, does it work to pass the parameter like this:
<script type='text/javascript'>
firstfunction(callbackfunction(param));
</script>
or am I doing it wrong?
In direct answer to your question, this does not work:
firstfunction(callbackfunction(param));
That will execute callbackfunction immediately and pass the return value from executing it as the argument to firstfunction which is unlikely what you want.
It is unclear from your question whether you should just change firstfunction() to pass two parameters to callbackfunction() when it calls the callback or whether you should make an anonymous function that calls the callback function with arguments.
These two options would look like this:
function firstfunction(callback) {
// code here
callback(arg1, arg2);
}
firstfunction(callbackfunction);
or
function firstfunction(callback) {
// code here
callback();
}
firstfunction(function() {
callbackfunction(xxx, yyy);
});
Use an anonymous function:
function foo( callback ) {
callback();
}
function baz( param ) {
console.log( param );
}
foo( function(){ baz('param') });
Adding parameters when calling a function.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply
xdaz already answered the simple version.
Here is an example with variable amount of parameters.
function someObject(){
this.callbacks=new Array();
this.addCallback=function(cb){
this.callbacks[this.callbacks.length]=cb
}
this.callCallbacks=function(){
//var arr=arguments; this does not seem to work
//arr[arr.length]="param2";
var arr = new Array();
for(i in arguments){
arr[i]=arguments[i];
}
arr[arr.length]="another param";
i=0;
for(i in this.callbacks){
this.callbacks[i].apply(null,arr);
//this.callbacks[i].apply(this,arr);
//this is a ref to currrent object
}
}
this.callCallbacksSimple=function(arg){
for(i in this.callbacks){
this.callbacks[i](arg,"simple parameter");
}
}
}
function callbackFunction(){
for(i in arguments){
console.log("Received argument: " + arguments[i]);
}
}
var ObjectInstance=new someObject();
ObjectInstance.addCallback(callbackFunction);
ObjectInstance.callCallbacks("call callbacks");
ObjectInstance.callCallbacksSimple("call callbacks");
function is key word, you can't use it as function name.
Let say your function name is foo, then you could do like below:
var param = 'what ever';
foo(function(response) {
callbackfunction(response, param);
});
I think this is what you're looking for.
Lets say you're using jQuery ajax to do something, and you're passing it named callbacks. Here we have an onError callback that you might use to log or handle errors in your application. It conforms to the jQuery Ajax error callback signature, except for an extra parameter that you might have wanted to add at the back
function onError(jqXHR, textStatus, errorThrown, yourOwnVariableThing) {
console.error('Something went wrong with ' + yourOwnVariableThing);
}
this is where your function would be called - but you want an extra parameter
$.ajax("/api/getSomeData/")
.done(onDone)
.fail(onError)
.always(onComplete);
So this is what you can do to add the extra parameter
$.ajax("/api/getSomeData/")
.done(onDone)
.fail(onError.bind(this, arguments[0], arguments[1], arguments[2], 'Moo Moo');
.always(onComplete);
arguments is an array in JavaScript that contains all arguments passed to a function, and so you're just passing those arguments along to the callback.
Arguments
Bind

Javascript function execution order

I am new to javascript and have a quick question. Say i have the following code:
function entryPoint()
{
callFunction(parameter);
}
function callFunction(parameter)
{
... //do something here
var anotherFunction = function () { isRun(true); };
}
My question is that when callFunction(parameter) is called, and the variable anotherFunction is declared, does isRun(true) actually execute during this instantiation? I am thinking it doesnt and the contents of the anotherFunction are only "stored" in the variable to be actually executed line by line when, somewhere down the line, the call anotherFunction() is made. Can anyone please clarify the function confusion?
It seems the confusion is this line of code
var anotherFunction = function () { isRun(true); };
This declares a variable of a function / lambda type. The lambda is declared it is not run. The code inside of it will not execute until you invoke it via the variable
anotherFunction(); // Now it runs
You almost described it perfectly.
anotherFunction just receives a reference to a newly created Function Object (yes, Functions are also Objects in this language) but it does not get executed.
You could execute it by calling
anotherFunction();
for instance.
You can write a simple test like so:
entryPoint();
function entryPoint()
{
alert("In entryPoint");
callFunction();
}
function callFunction()
{
alert("In callFunction");
var anotherFunction = function () { isRun(); };
}
function isRun()
{
alert("In isRun");
}
​
And, the answer is no, isRun() does not get called.

Javascript callback function and parameters [duplicate]

This question already has answers here:
Pass an extra argument to a callback function
(5 answers)
Closed 6 years ago.
I want to something similar to this:
function AjaxService()
{
this.Remove = function (id, call_back)
{
myWebService.Remove(id, CallBack)
}
function CallBack(res) {
call_back(res);
}
}
so my calling program will be like this:
var xx = new AjaxService();
xx.Remove(1,success);
function success(res)
{
}
Also if I want to add more parameters to success function how will I achieve it.
Say if I have success function like this:
var xx = new AjaxService();
//how to call back success function with these parameters
//xx.Remove(1,success(22,33));
function success(res,val1, val2)
{
}
Help will be appreciated.
Use a closure and a function factory:
function generateSuccess (var1,var2) {
return function (res) {
// use res, var1 and var2 in here
}
}
xx.Remove(1,generateSuccess(val1,val2));
What you're passing here is not the generateSuccess function but the anonymous function returned by generateSuccess that looks like the callback expected by Remove. val1 and val2 are passed into generateSuccess and captured by a closure in the returned anonymous function.
To be more clear, this is what's happening:
function generateSuccess (var1,var2) {
return function (res) {
// use res, var1 and var2 in here
}
}
var success = generateSuccess(val1,val2);
xx.Remove(1,success);
Or if you prefer to do it inline:
xx.Remove(1,(function(var1,var2) {
return function (res) {
// this is your success function
}
})(val1,val2));
not as readable but saves you from naming the factory function. If you're not doing this in a loop then Xinus's solution would also be fine and simpler than my inline version. But be aware that in a loop you need the double closure mechanism to disconnect the variable passed into the callback function from the variable in the current scope.
You can pass it as anonymous function pointer
xx.Remove(1,function(){
//function call will go here
success(res,val1, val2);
});
one way to do this:
function AjaxService {
var args_to_cb = [];
this.Remove = function (id, call_back, args_to_callback_as_array) {
if( args_to_callback_as_array!=undefined )
args_to_cb = args_to_callback_as_array;
else
args_to_cb = [];
myWebService.Remove(id, CallBack)
}
function CallBack(res) {
setTimeout( function(){ call_back(res, args_to_cb); }, 0 );
}
}
So you can use it like this:
var service = new AjaxService();
service.Remove(1,success, [22,33]);
function success(res,val1, val2)
{
alert("result = "+res);
alert("values are "+val1+" and "+val2);
}
I usually have the callback execute using a setTimeout. This way, your callback will execute when it gets the time to do so. Your code will continue to execute meanwhile, e.g:
var service = new AjaxService();
service.remove(1, function(){ alert('done'); }); // alert#1
alert('called service.remove'); // alert#2
Your callback will execute after alert#2.
Of course, in case of your application, it will happen so automatically since the ajax callback itself is asynchronous. So in your application, you had better not do this.
Cheers!
jrh

calling a javascript function (in original function) from called function?

Is there anyway to calling a function from another function .. little hard to explain. heres in example. One function loads html page and when ready it calls the original function.
I think i need to pass in a reference but unsure how to do this... if i set it to "this" - it doesn't seem to work
ANy ideas?
order.prototype.printMe = function(){
order_resume.loadthis("myTestPage.html", "showData");
}
order.prototype.testme= function(){
alert("i have been called");
}
//Then when in "loadthis" need to call
orderRsume.prototype.loadthis= function(){
// DO SOME STUFF AND WHEN LOADS IT ARRIVES IN OnReady
}
order.prototype.OnReady= function(){
/// NEED TO CALL ORIGINAL "testme" in other function
}
It's not clear for me what you really want to do. In JS functions are first-class objects. So, you can pass function as a parameter to another function:
Cook("lobster",
"water",
function(x) { alert("pot " + x); });
order.somefunc = function(){
// do stuff
}
order.anotherone = function(func){
// do stuff and call function func
func();
}
order.anotherone(order.somefunc);
And if you need to refer to unnamed function from it's body, following syntax should work:
order.recursivefunc = function f(){
// you can use f only in this scope, afaik
f();
};
I slightly changed the signature of your loadthis function aloowing it to be passed the order to actually load.
I also assumed that your doSomeStuff function accepts a callback function. I assumed that it may be an AJAX call so this would be trivial to call a callback function at the end of the AJAX call. Comment this answer if you need more info on how to fire this callback function from your AJAX call.
order.prototype.printMe = function(){
order_resume.load(this, "myTestPage.html", "showData");
}
order.prototype.testme= function(){
alert("i have been called");
}
//Then when in "loadthis" need to call
orderRsume.prototype.load = function(order, page, action){
// DO SOME STUFF AND WHEN LOADS IT ARRIVES IN OnReady
doSomeStuff(page, action, function()
{
order.OnReady();
});
}
order.prototype.OnReady= function(){
/// NEED TO CALL ORIGINAL "testme" in other function
this.testme();
}

Categories